3

I want to implement foldable for

data Constant a b = Constant a

This is my straightforward attempt:

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

The part of the compilation error I want to understand is:

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

as you can see the folding function takes the "phantom type" (?) a1 from the Constant which I do not have access to; I only have access to the a.

How do I solve this? Please do explain your solution, because I am rather confused.

The whole compilation error is:

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.
The Unfun Cat
  • 29,987
  • 31
  • 114
  • 156
  • You can not. You can only define a `Foldable (C a)` instance for `data C a b = C b`. In your case, you would need something like `instance Foldable (\a -> Constant a b)` but we do not have type-level lambdas in Haskell. – chi May 24 '16 at 17:35
  • Great question, I was just wondering this while trying to implement foldl – Galder Zamarreño Jul 04 '17 at 14:54

2 Answers2

9

Constant a b doesn't contain any b-s, so we fold over it as if it were an empty list of b-s:

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

a in Constant a b is not relevant to the Foldable instance, since that only concerns the last parameter. Hence you can't really make use of a in your definition.

András Kovács
  • 29,931
  • 3
  • 53
  • 99
2

I think the only possibility is:

data Constant a b = C a

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

which is the trivial solution.

It might be instructive to see why you can do it for this definition:

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

Here t is Constant' a, so

  • the type t b is Constant' a b. Values of this type have the structure C bval for some value bval of type b.
  • f has type b -> m, so we can apply f to bval

In the other case, though, we don't have a value from b to apply to f, so the best we can do is return mempty.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
ErikR
  • 51,541
  • 9
  • 73
  • 124