我正在尝试使用以下代码在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 = ""
第一个代码出了什么问题?
答案 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 = "_"