this SO post的已接听答案显示了如何使用case ... of
在多个模式匹配中使用where
定义。现在在我的情况下,这似乎不起作用(ghc抱怨:Variable not in scope: x
)。
data PolyTree a = PolyBranch a (PolyTree a) (PolyTree a) | PolyLeaf a
paths' :: PolyTree a -> [a] -> PolyTree [a]
paths' pt buf = case pt of
(PolyLeaf x) -> PolyLeaf buf'
(PolyBranch x pt1 pt2) -> PolyBranch buf' (paths' pt1 buf') (paths' pt2 buf')
where buf' = buf ++ [x]
我可以用另一种方式吗?
答案 0 :(得分:2)
在您的示例中,buf'
是根据x
定义的,case
由内部where
表达式绑定,而paths' pt buf =
(case ... of ... -> ...(1) ; ... -> ...(2) )
where ...(3)
实际上是表达式的“外部”在右手边。
x
(1)
仅在(2)
和(3)
中可见,但在x
中不可见。 (1)
和(2)
中x
的出现应该被视为两个具有相同名称的变量。
如果您希望在where
子句中看到=
,则必须将其绑定在x
符号的左侧。一种方法是从PolyTree
类型中考虑data PolyTree a = PolyTree a (PolyBranch a)
data PolyBranch a = PolyBranch (PolyTree a) (PolyTree a) | PolyLeaf
paths' (PolyTree x pt) buf = ...
where buf' = buf ++ [x]
。
{{1}}
答案 1 :(得分:0)
在这一点上将两个名为x
的变量放在范围内需要非常奇怪的范围(和alpha转换)规则。
相反,您可以单独处理每个x
。
paths' :: PolyTree a -> [a] -> PolyTree [a]
paths' pt buf = case pt of
(PolyLeaf x) -> let
buf' = buf ++ [x]
in PolyLeaf buf'
(PolyBranch x pt1 pt2) -> let
buf' = buf ++ [x]
in PolyBranch buf' (paths' pt1 buf') (paths' pt2 buf')
最好删除case
并使用多个定义方程式。您仍然需要复制where
。
paths' (PolyLeaf x) buf = PolyLeaf buf'
where buf' = buf ++ [x]
paths' (PolyBranch x pt1 pt2) buf = PolyBranch buf' (paths' pt1 buf') (paths' pt2 buf')
where buf' = buf ++ [x]
答案 2 :(得分:0)
其他答案已经解释了原因,但是这里有另外两种写作方式,我更倾向于他们的建议:
paths' :: PolyTree a -> [a] -> PolyTree [a]
paths' pt buf = case pt of
(PolyLeaf x) -> PolyLeaf (addBuf x)
(PolyBranch x pt1 pt2) ->
let buf' = addBuf x in
PolyBranch buf' (paths' pt1 buf') (paths' pt2 buf')
where addBuf x = buf ++ [x]
paths' :: PolyTree a -> [a] -> PolyTree [a]
paths' pt buf = case pt of
(PolyLeaf x) -> PolyLeaf buf'
(PolyBranch x pt1 pt2) -> PolyBranch buf' (paths' pt1 buf') (paths' pt2 buf')
where buf' = buf ++ [getX pt]
getX (PolyLeaf x) = x
getX (PolyBranch x pt1 pt2) = x