Reputation: 21
I tryied to adapt some exercises of the excelent book "Land of Lisp" of Conrad Barski in order to learn Haskell. The idea is to make a simple text game engine.
Concretely I tried :
type Clau = String
type Descripcio = String
type Valors = [String]
-- NOTE : Ideas of types http://learnyouahaskell.com/making-our-own-types-and-typeclasses
data Lloc = Lloc String String String deriving (Show)
llocSituacio :: Lloc -> String
llocSituacio (Lloc situacio _ _ ) = situacio
llocDireccio :: Lloc -> String
llocDireccio (Lloc _ direccio _) = direccio
llocPas :: Lloc -> String
llocPas ( Lloc _ _ pas) = pas
nodes :: [(Clau,Descripcio)]
nodes = [("living-room","you are in the living-room. a wizard is snoring loudly on the couch.")
,("garden","you are in a beautiful garden. there is a well in front of you.")
, ("attic", "you are in the attic. there is a giant welding torch in the corner.")]
edges :: [([Char], [Lloc])]
edges = [ ("living-room", [(Lloc "garden" "west" "door"), ( Lloc "attic" "upstairs" "ladder") ])
, ("attic", [(Lloc "living-room" "east" "door")])
, ("garden", [(Lloc "living-room" "east" "door")])]
describePath :: Lloc -> String
describePath e = "There is " ++ llocPas e ++ " going " ++ llocDireccio e ++ " from here."
At first, it seems that works well. For example:
*TextGame> describePath (Lloc "living-room" "east" "door")
"There is door going east from here."
But when I try to apply the function to the list I got this error:
situacio = "garden"
map (describePath) (lookup situacio edges)
<interactive>:2:22: error:
• Couldn't match expected **type ‘[Maybe Lloc]’**
with actual **type ‘Maybe [Lloc]’**
• In the second argument of ‘map’, namely ‘(lookup situacio edges)’
In the expression: map (describePath) (lookup situacio edges)
In an equation for ‘it’:
it = map (describePath) (lookup situacio edges)
The error is clear, but I do not manage to solve it. I want to parse the list of Maybe's values and print the path with the function describePath that works well:
Any ideas? Also, if somebody wants to share alternatives or feel that this code could be more in Haskell style, please feel free to talk about it.
Upvotes: 1
Views: 535
Reputation: 21
Thanks a lot chi, it works perfectly. I just made a new function:
describePaths situacio edges = case lookup situacio edges of
Nothing -> []
Just locs -> map describePath locs
.. and works pretty well:
*TextGame> situacio = "living-room"
*TextGame> describePaths situacio edges
["There is door going west from here.","There is ladder going upstairs from here."]
But I see that I do not fully understand the <$> operator. I follow the comments of : What does <$> mean in Haskell?
So I follow the suggestion : https://hoogle.haskell.org/?hoogle=%3C$%3E
This is call a Functor:
(<$>) :: Functor f => (a->b) -> f a -> f b
That actually is exactly the same as fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
It seems that are the same:
*TextGame> (*2) <$> [1..3]
[2,4,6]
*TextGame> fmap (*2) [1..3]
[2,4,6]
But, actually they are different:
*TextGame> map describePath <$> lookup situacio edges
Just ["There is door going west from here.","There is ladder going upstairs from here."]
*TextGame> fmap (describePath) (lookup situacio edges)
<interactive>:30:22: error:
• Couldn't match type ‘[Lloc]’ with ‘Lloc’
Expected type: Maybe Lloc
Actual type: Maybe [Lloc]
....
Could someone put a little more light on it ? I do not fully understand why 'fmap (describePath) (lookup situacio edges)' do not work? (I am playing with Maybe's and Just's but ...)
Upvotes: 1
Reputation: 116139
There might be some more advanced library helpers, but I think you should first learn how to handle Maybe
s in the most basic (and general) way: use pattern matching.
case lookup situacio edges of
Nothing -> [] -- not found, how do you want to handle this case?
Just locs -> map describePath locs
Oftentimes, one wants instead to rewrap the result in another Maybe
, e.g.:
case lookup situacio edges of
Nothing -> Nothing -- not found
Just locs -> Just (map describePath locs)
and in such case, we can use a library helper function to shorten the code:
map describePath <$> lookup situacio edges
Upvotes: 6