使用防护装置的功能中的变量不在范围错误中

时间:2017-10-21 18:38:16

标签: haskell

我正在尝试使用以下代码在Haskell中打印链接列表:

data List = Node {value:: Double, next:: List}
          |   Empty

printList :: List -> String
printList x | x == (Node v n) = show v ++ " " ++ printList n
            | otherwise = show '_'

收到编译错误:

:load scratch.hs
[1 of 1] Compiling Main             ( scratch.hs, interpreted )

scratch.hs:5:26: error: Variable not in scope: v :: Double

scratch.hs:5:28: error: Variable not in scope: n :: List

scratch.hs:5:38: error: Variable not in scope: v

scratch.hs:5:53: error: Variable not in scope: n :: List
Failed, modules loaded: none.

虽然我可以使用没有警卫的模式匹配来做同样的事情。

printList (Node v n) = show v ++ " " ++ printList n
printList Empty = ""

第一个代码出了什么问题?

1 个答案:

答案 0 :(得分:4)

您不使用等式检查执行模式匹配:可能认为两种不同的模式相等。

所以你可以做的是在你的函数的一个子句的头部定义一个模式。例如:

printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'

所以现在Haskell将为给定的List检查它是否与Node v n模式匹配,如果是,则解压缩该元素并将头部分配给v并将尾部分配给{ {1}}。

然而,我们仍然可以改进代码。通常,您最好不要使用通配符模式,而是使用所有可能的模式。因为如果您以后想要更改n的定义,编译器会给您一个警告,告诉您忘记了一个模式:

List

我们可以改进的另一件事是使用printList :: List -> String printList (Node v n) = show v ++ " " ++ printList n printList Empty = show '_'而不是"_"。由于 show '_'会在内容中添加引号。例如:

show '_'

最后,我们还可以使用" cons"建筑物附加单身人士名单:

printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"