如何为Constant a b = Constant a实现可折叠实例?

时间:2016-05-24 17:12:20

标签: haskell types foldable

我想为

实现可折叠
data Constant a b = Constant a

这是我直截了当的尝试:

instance Foldable (Constant a) where
  foldr f b (Constant a) = f a b

我想了解的编译错误部分是:

Couldn't match expected type ‘a1’ with actual type ‘a’
‘a1’ is a rigid type variable bound by the type signature for
foldr :: (a1 -> b -> b) -> b -> Constant a a1 -> b

你可以看到折叠功能采用"幻像类型"来自Constant的(?)a1我无法访问;我只能访问a

我该如何解决这个问题?请解释一下你的解决方案,因为我很困惑。

整个编译错误是:

try2/chap20/ex1.hs:9:30: Couldn't match expected type ‘a1’ with actual type ‘a’ …
      ‘a’ is a rigid type variable bound by
          the instance declaration
          at /Users/moron/code/haskell/book/try2/chap20/ex1.hs:8:10
      ‘a1’ is a rigid type variable bound by
           the type signature for
             foldr :: (a1 -> b -> b) -> b -> Constant a a1 -> b
           at /Users/moron/code/haskell/book/try2/chap20/ex1.hs:9:3
    Relevant bindings include
      a :: a
        (bound at /Users/moron/code/haskell/book/try2/chap20/ex1.hs:9:23)
      f :: a1 -> b -> b
        (bound at /Users/moron/code/haskell/book/try2/chap20/ex1.hs:9:9)
      foldr :: (a1 -> b -> b) -> b -> Constant a a1 -> b
        (bound at /Users/moron/code/haskell/book/try2/chap20/ex1.hs:9:3)
    In the first argument of ‘f’, namely ‘a’
    In the expression: f a b
Compilation failed.

2 个答案:

答案 0 :(得分:9)

Constant a b不包含任何b - s,因此我们将其折叠为好像是b的空列表 - s:

instance Foldable (Constant a) where
    foldr f z (Constant a) = z
a中的

Constant a bFoldable实例无关,因为这只涉及最后一个参数。因此,您无法在定义中真正使用a

答案 1 :(得分:2)

我认为唯一的可能性是:

data Constant a b = C a

-- foldMap :: Monoid m => (b -> m) -> t b -> m
instance Foldable (Constant a) where
  foldMap f (C a) = mempty

这是一个简单的解决方案。

了解为什么你可以为这个定义做到这一点可能是有益的:

data Constant' a b = C' b

-- foldMap :: Monoid m => (b -> m) -> t b -> m
instance Foldable (Constant' a) where
  foldMap f (C' a) = f a

此处tConstant' a,所以

  • 类型t bConstant' a b。对于C bval类型的某个值bval,此类型的值具有结构b
  • f的类型为b -> m,因此我们可以将f应用于bval

但在另一种情况下,我们没有b的值来申请f,因此我们所做的最好就是返回mempty