Haskell 使用保护的函数中存在变量不在范围内错误
我正在尝试使用以下代码在Haskell中打印链接列表:Haskell 使用保护的函数中存在变量不在范围内错误,haskell,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
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 '_'
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
我们可以改进的另一件事是使用“
而不是show'
。因为show'.
会在内容中添加引号。例如:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
printList::List->String
打印列表(节点v n)=显示v++++++++
printList Empty=“\u1”
最后,我们还可以使用一个“cons”结构来附加一个单例列表:
printList :: List -> String
printList (Node v n) = show v ++ ' ' : printList n
printList Empty = "_"
printList::List->String
打印列表(节点v n)=显示v++'':打印列表n
printList Empty=“\u”
您不使用相等检查进行模式匹配:可能两个不同的模式被视为相等
因此,您可以在函数的某个子句的头部定义一个模式。例如:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
我们可以改进的另一件事是使用“
而不是show'
。因为show'.
会在内容中添加引号。例如:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
printList::List->String
打印列表(节点v n)=显示v++++++++
printList Empty=“\u1”
最后,我们还可以使用一个“cons”结构来附加一个单例列表:
printList :: List -> String
printList (Node v n) = show v ++ ' ' : printList n
printList Empty = "_"
printList::List->String
打印列表(节点v n)=显示v++'':打印列表n
printlistempty=“”
在printList(Node v n)
中,v
和n
是参数,但在x==(Node v n)
中,它们是两个未定义的变量。@ForceBru那么有没有办法区分x使用的数据构造函数?在printList(Node v n)
中,v
和n
是参数,但是在x==(Node v n)
中,它们是两个未定义的变量。@ForceBru那么有没有办法区分x使用的是哪个数据构造函数呢?但是我之前写的一段代码有一个函数参数x
与数据构造函数行Meter
进行比较。代码如下:data MetricUnit=Meter | L | kg推导(Show,Eq)
returnMetricSymbol x | x==Meter=“m”| x==L=“L”| x==kg=“kg”@SafwanAhmad:这是因为(1)您添加了derving Eq
,并且(2)这里您只检查等式,不需要解包构造函数,代码中没有您感兴趣的参数。所以我的理解是,在guard语句中使用数据构造函数实际上是在创建新变量,而如果使用相同的数据构造函数作为函数参数,则它是模式匹配的。这意味着我在上面评论中的代码完全是偶然工作的,因为Meter
正在创建一个新变量,该变量将与x
进行比较,并且比较是可能的,因为我已导出Eq
。对吧?或多或少。通过导出Eq
,您已经隐式定义了一个函数(==)::MetricUnit->MetricUnit->Bool
。但是对于Haskell来说,=
只是另一个函数。因此,对于Haskell来说,x==Meter
并不比otherFunction x Meter
更特殊。它只是计算这个值,然后返回True
。但是我前面编写的一段代码有一个函数参数x
,与数据构造函数lineMeter
进行比较。代码如下:data MetricUnit=Meter | L | kg推导(Show,Eq)
returnMetricSymbol x | x==Meter=“m”| x==L=“L”| x==kg=“kg”@SafwanAhmad:这是因为(1)您添加了derving Eq
,并且(2)这里您只检查等式,不需要解包构造函数,代码中没有您感兴趣的参数。所以我的理解是,在guard语句中使用数据构造函数实际上是在创建新变量,而如果使用相同的数据构造函数作为函数参数,则它是模式匹配的。这意味着我在上面评论中的代码完全是偶然工作的,因为Meter
正在创建一个新变量,该变量将与x
进行比较,并且比较是可能的,因为我已导出Eq
。对吧?或多或少。通过导出Eq
,您已经隐式定义了一个函数(==)::MetricUnit->MetricUnit->Bool
。但是对于Haskell来说,=
只是另一个函数。因此,对于Haskell来说,x==Meter
并不比otherFunction x Meter
更特殊。它只是计算这个值,然后返回True
。