变量未在范围上的错误使用功能卫士
我尝试使用下面的代码打印在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 = ""
第一个代码有什么问题?
通过使用相等性检查,您不会做模式匹配:有可能两个不同的模式被认为是相等的。
所以你可以做的是定义一个模式在你的函数的一个子句的头部。例如:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'
所以现在哈斯克尔会,因为如果它与Node v n
模式匹配,和一个给定的List
检查,如果这样解压元素和分配头v
和尾部n
。
但是我们仍然可以改进代码。通常你最好不要使用通配符模式,而是使用所有可能的模式。因为如果你以后想改变的List
定义,编译器可以给你,你忘了图案的警告:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = show '_'
我们可以改善的另一件事是在show '_'
使用"_"
。由于show '_'
会将内容加到中。例如:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
最后,我们还可以使用 “缺点” 建设上有一个单列表附加:
printList :: List -> String
printList (Node v n) = show v ++ ' ' : printList n
printList Empty = "_"
但我之前编写的一段代码有一个函数参数'x',与数据构造函数行'Meter'比较。代码如下:'数据MetricUnit = Meter |升| |千克 派生(Show,Eq)''returnMetricSymbol x | x ==米=“m” | x == Liter =“L” | x == Kilogram =“kg”' –
@SafwanAhmad:这是因为(1)你添加了'derving Eq',并且(2)在这里你只检查是否相等,你不需要*解压缩构造函数,没有参数在你感兴趣的代码中。 –
好吧,我的理解是,在guard语句中使用Data构造函数本质上是创建新变量,而如果我使用相同的Data构造函数作为函数参数,则它是模式匹配的。这意味着我的代码在上面的评论中是纯粹的机会,因为'Meter'正在创建一个新变量,与'x'进行比较,并且可以进行比较,因为我推导出了'Eq'。对? –
在'的printList(节点VN)','v'和'N'是参数,但在'x ==(Node vn)'中,它们是两个未定义的变量。 – ForceBru
@ForceBru所以有办法区分哪个数据构造函数x正在使用? –