如何处理 Haskell 中的“可能 [值]”列表?
Posted
技术标签:
【中文标题】如何处理 Haskell 中的“可能 [值]”列表?【英文标题】:How to deal with a list of 'Maybe [values]' in Haskell? 【发布时间】:2021-08-19 21:14:17 【问题描述】:为了学习 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."
但是当我尝试将函数应用到列表时,我得到了这个错误:
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)
错误很明显,但我无法解决它。我想解析 Maybe 的值列表并使用运行良好的函数 describePath 打印路径:
有什么想法吗?此外,如果有人想分享替代方案或觉得此代码可能更符合 Haskell 风格,请随时讨论。
【问题讨论】:
也许这个旧答案有帮助? ***.com/questions/3375483/… 它是map-function,而不是map。 【参考方案1】:可能有一些更高级的库助手,但我认为您应该首先学习如何以最基本(和一般)的方式处理Maybe
s:使用模式匹配。
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)
在这种情况下,我们可以使用库辅助函数来缩短代码:
map describePath <$> lookup situacio edges
【讨论】:
非常感谢您的回答!它完美地工作!但是我意识到我不完全理解运算符 ,fmap 不一样吧!?它包括您指出的模式!?这就是区别?! @Mandormanf <$> x
恰好是 Maybe
函子的 fmap f x
:它在 Just
的“下方”应用 f
,并保持 Nothing
原样。【参考方案2】:
非常感谢chi,它工作得很好。我刚刚做了一个新功能:
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."]
但我发现我并不完全理解 运算符。我关注的是:What does <$> mean in Haskell?
所以我遵循建议:https://hoogle.haskell.org/?hoogle=%3C$%3E
这是一个 Functor:
(<$>) :: 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 但是......)
【讨论】:
您从上一个示例中删除了map
,正确的翻译是fmap (map describePath) (lookup situacio edges)
。这里的fmap
处理Maybe
,map
处理[Lloc]
中的列表。
哦,我明白了!我现在明白了!非常感谢!以上是关于如何处理 Haskell 中的“可能 [值]”列表?的主要内容,如果未能解决你的问题,请参考以下文章