在 guards 中使用 case 表达式时出现解析错误 haskell

Parse error when using case expression inside guards haskell

我是 Haskell 的新手,我遇到语法问题。我想要做的是给定数据和这种数据类型的树,找到树中相应节点的路径。我相信我的功能逻辑是正确的,但我不确定如何使其有效 Haskell。我试过将制表符更改为空格。

-- | Binary trees with nodes labeled by values of an arbitrary type.
data Tree a
   = Node a (Tree a) (Tree a)
   | End
  deriving (Eq,Show)

-- | One step in a path, indicating whether to follow the left subtree (L)
--   or the right subtree (R).
data Step = L | R
  deriving (Eq,Show)

-- | A path is a sequence of steps. Each node in a binary tree can be
--   identified by a path, indicating how to move down the tree starting
--   from the root.
type Path = [Step]
pathTo :: Eq a => a -> Tree a -> Maybe Path
pathTo a End = Nothing
pathTo a (Node b l r)
    | a == b = Just []
    | case (pathTo a l) of
                Just p  -> Just [L:p]
                Nothing -> case (pathTo a r) of
                                    Just p  -> Just [R:p]
                                    Nothing -> Nothing

这是错误:

  parse error (possibly incorrect indentation or mismatched brackets)

这里的根本问题是这看起来不像守卫:守卫是类型为 Bool 的表达式,它决定了守卫是否“开火”。这可能是`否则:

pathTo :: Eq a => a -> Tree a -> Maybe Path
pathTo a End = Nothing
pathTo a (Node b l r)
    | a == b = Just []
    | <b>otherwise</b> = case (pathTo a l) of
                Just p  -> <b>Just (L:p)</b>
                Nothing -> case (pathTo a r) of
                                    Just p  -> <b>Just (R:p)</b>
                                    Nothing -> Nothing

这也揭示了一些额外的错误:Just [L:p] 是一个 Maybe [[Step]],你可能想使用 Just (L:p),同样适用于 Just [R:p]

此外,您不需要使用嵌套的 cases,您可以使用 Alternative 类型类:

import Control.Applicative((<|>))

pathTo :: Eq a => a -> Tree a -> Maybe Path
pathTo a End = Nothing
pathTo a (Node b l r)
    | a == b = Just []
    | <b>otherwise</b> = ((L:) <$> pathTo a l) <|> ((R:) <$> pathTo a r)

如果是 Just …,这里 x <|> y 将取 x,否则 y。我们使用 (L:) <$> … 来添加包含在 Just 数据构造函数中的列表,或者 return Nothing 以防 Nothing.