如何处理 Haskell 中的“可能 [值]”列表?

Man*_*man 2 lisp dictionary haskell functional-programming maybe

为了学习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." 
Run Code Online (Sandbox Code Playgroud)

起初,似乎效果很好。例如:

*TextGame> describePath (Lloc "living-room"  "east"  "door")
"There is door going east from here."
Run Code Online (Sandbox Code Playgroud)

但是当我尝试将该函数应用于列表时,我收到了这个错误:

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)
Run Code Online (Sandbox Code Playgroud)

错误很明显,但我无法解决它。我想解析Maybe的值列表并使用运行良好的函数describePath打印路径:

有任何想法吗?另外,如果有人想分享替代方案或觉得此代码可能更符合 Haskell 风格,请随时讨论。

chi*_*chi 5

可能有一些更高级的库助手,但我认为您应该首先学习如何以Maybe最基本(和通用)的方式处理s:使用模式匹配。

case lookup situacio edges of
   Nothing   -> [] -- not found, how do you want to handle this case?
   Just locs -> map describePath locs
Run Code Online (Sandbox Code Playgroud)

通常,人们希望将结果重新包装在另一个中Maybe,例如:

case lookup situacio edges of
   Nothing   -> Nothing -- not found
   Just locs -> Just (map describePath locs)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们可以使用库辅助函数来缩短代码:

map describePath <$> lookup situacio edges
Run Code Online (Sandbox Code Playgroud)