[英]How to deal with a list of 'Maybe [values]' in Haskell?
为了学习 Haskell,我尝试改编康拉德·巴尔斯基 (Conrad Barski) 的名著《Land of Lisp》的一些练习。 这个想法是制作一个简单的文本游戏引擎。
具体我试过:
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."
起初,它似乎运作良好。 例如:
*TextGame> describePath (Lloc "living-room" "east" "door")
"There is door going east from here."
但是当我尝试将 function 应用于列表时,我收到了这个错误:
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)
错误很明显,但我无法解决它。 我想解析可能的值列表并使用运行良好的 function describePath 打印路径:
有任何想法吗? 另外,如果有人想分享替代方案或觉得此代码可能更像 Haskell 风格,请随时讨论。
可能有一些更高级的库助手,但我认为您应该首先学习如何以最基本(和一般)的方式处理Maybe
:使用模式匹配。
case lookup situacio edges of
Nothing -> [] -- not found, how do you want to handle this case?
Just locs -> map describePath locs
通常,人们希望将结果重新包装在另一个Maybe
中,例如:
case lookup situacio edges of
Nothing -> Nothing -- not found
Just locs -> Just (map describePath locs)
在这种情况下,我们可以使用库助手 function 来缩短代码:
map describePath <$> lookup situacio edges
非常感谢chi,它工作得很好。 我刚做了一个新的function:
describePaths situacio edges = case lookup situacio edges of
Nothing -> []
Just locs -> map describePath locs
..并且效果很好:
*TextGame> situacio = "living-room"
*TextGame> describePaths situacio edges
["There is door going west from here.","There is ladder going upstairs from here."]
但我发现我并不完全理解 <$> 运算符。 我遵循以下评论: Haskell 中的 <$> 是什么意思?
所以我遵循建议: https://hoogle.haskell.org/?hoogle=%3C$%3E
这称为函子:
(<$>) :: Functor f => (a->b) -> f a -> f b
这实际上与 fmap 完全相同:
fmap :: Functor f => (a -> b) -> f a -> f b
似乎是一样的:
*TextGame> (*2) <$> [1..3]
[2,4,6]
*TextGame> fmap (*2) [1..3]
[2,4,6]
但是,实际上它们是不同的:
*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]
....
有人可以多说一点吗? 我不完全明白为什么'fmap(describePath)(查找位置边缘)'不起作用? (我正在玩 Maybe's 和 Just's 但是......)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.