范围:多个多态模式的位置

时间:2017-04-22 12:31:16

标签: haskell

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]

我可以用另一种方式吗?

3 个答案:

答案 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