Haskell: understanding nested lists

I have an assignment for school, I need help. So far I have created two types, Argument

and Predicate

, according to the assignment instructions.

In this project I have to create a list called "context" of the arguments (or objects) in the world AND a list of facts about those objects in a list called "facts".

So, for example, the context list has arguments "john" and "boston", and then in our fact list, we can create a predicate with a function fly

to have the fact "fly john to_boston", which to

means that John is flying to Boston.

For the final stage of the project, we should be able to ask Haskell: "qWhere fly john" and ask Haskell to find the list of contexts for "john" and use that to find the list of facts for "fly" and "john" to eventually return "to_boston" or "boston".

I understand this is a nested list comprehension, but I don't understand how to get Haskell to return "to_boston" as soon as it "flies john". I'll include the bits of code below (scroll down for what I've been working on):

{-# LANGUAGE MultiParamTypeClasses #-}

-- GL TYPES
data Type = HUMN |         -- human
            ANIM |         -- animate
            ORGN |         -- organic
            ORGZ |         -- organization
            PHYS |         -- physical object
            ARTF |         -- artifact
            EVNT |         -- event
            PROP |         -- proposition
            INFO |         -- information
            SENS |         -- sensation
            LOCA |         -- location
            TIME |         -- time period
            ATTD |         -- attitude
            EMOT |         -- emotion
            PPTY |         -- property
            OBLG |         -- obligation
            RULE           -- rule
                 deriving (Show, Eq, Enum)

-- CUSTOM DATA TYPES
data Argument = Argument { ttype :: Type, value :: String } 
                  deriving (Show, Eq)

data Predicate = Predicate { lemma :: String
                           , arguments :: [Argument] } 
                  deriving (Show, Eq)

type Context = [Argument]

-- CREATE SEMANTICALLY TYPED ARGUMENTS AS FOLLOWS
date :: String -> Argument
date s = Argument { ttype = TIME, value = s }

time :: String -> Argument
time s = Argument { ttype = TIME, value = s }

location :: String -> Argument
location s = Argument { ttype = LOCA, value = s }

human :: String -> Argument
human s = Argument { ttype = HUMN, value = s }

phys :: String -> Argument
phys s = Argument { ttype = PHYS, value = s }

artifact :: String -> Argument
artifact s = Argument { ttype = ARTF, value = s }

animate :: String -> Argument
animate s = Argument { ttype = ANIM, value = s }

-- CREATE ENTITIES/PPs AS FOLLOWS
may15 = date "May 15, 2014"
sevenAM = time "7:00"
sandiego = location "San Diego"
john = human "John"
mary = human "Mary"
boston = location "Boston"
ball = phys "ball"
car = artifact "car"
cat = animate "cat"
mouse = animate "mouse"
to_boston = to boston

context = [
        may15,
        sevenAM,
        sandiego,
        john,
        mary,
        boston,
        ball,
        cat,
        mouse
      ]

-- HELPER FUNCTIONS
getValue :: Argument -> String
getValue c = value c

getType :: Argument -> Type
getType c = ttype c

isType :: Argument -> Type -> Bool
isType c t = (ttype c == t)

-- CREATE PREPOSITIONS AS FOLLOWS
to :: Argument -> Predicate
to x = Predicate { lemma = "to", arguments = [x] }

-- CREATE VERBS AS FOLLOWS
class Fly a b where
      fly :: a -> b -> Predicate

instance Fly Argument Argument where
      fly x y = Predicate { lemma = "fly", arguments = [x, y] }

--overwrite lemma, 
instance Fly Argument Predicate where
      fly x y = Predicate { lemma = lemma y
                          , arguments = [x, arguments y !! 0] }

facts = [fly john to_boston, fly mary to_boston]

-- THIS IS WHERE I'M STUCK\/
qWhere :: (Argument -> Argument -> Predicate) -> Argument 
                                              -> [[Argument]]
qWhere f x = [[arguments z | ]| z <- facts, x `elem` (arguments z)] 

-- THIS RETURNS THE ENTIRE STATEMENT:
qWhere f x = [[arguments z | ]| z <- facts, x `elem` (arguments z)] 

      

+3


source to share


1 answer


I don't think you need / need nested list comprehension. You first need to understand that list comprehension is really just syntactic sugar.

But we can use the syntax let ... in

to use multiple lists. The solution might look like this:



qWhere :: (Argument -> Argument -> Predicate)
       -> Argument
       -> [[Argument]]
qWhere f x = case find (== x) context of
  Just e ->
        -- first we get all facts about e.g. john
    let personFacts = [z | z <- facts, e `elem` arguments z]
        -- then we get all facts when we apply f to john and
        -- any other arguments that exist in john
        actionFacts = fmap (f e) (concatMap arguments personFacts)
        -- and extract all arguments of those facts
        actionArgs  = concatMap arguments actionFacts
        -- and can finally build the actual list of facts,
        -- reduced by checking if the argument "john" is in one of our
        -- actionArgs where we applied f to
    in map arguments [z | z <- personFacts, e `elem` actionArgs]
  Nothing -> []

      

You may need to import Data.List

.

+1


source







All Articles