3

I have a data type:

data Box a b = Box a b

I want to create a Foldable instance of Box and since the Foldable instance has to be given something of kind * -> *, I'll declare the instance as:

instance Foldable (Box a) where
  foldr f x (Box r s) = undefined

Now I can only do something like:

foldr f x (Box r s) = f s x

in the definition of foldr but what if instead of operating on s, I want to to something like:

foldr f x (Box r s) = f r x

The compiler doesn't let me do this so what is the proper way to go about it?

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
Muhammad Ali
  • 599
  • 1
  • 7
  • 15
  • @chi oops - thanks ... sadly it's to late to edit the thing and I don't know if it's of any worth ... so I guess I'll remove it – Random Dev Mar 11 '16 at 20:07
  • 1
    The proper way? Some options. 1. Do not use `Foldable` because you want something that is semantically different. 2. Make `type B a = Box a a ; instance Foldable B where` then fold over both elements. 3. Make an instance for a newtype wrapper `newtype FlipBox a b = FBox (Box b a) ; instance Foldable (FlipBox a) where ...`. – Thomas M. DuBuisson Mar 11 '16 at 20:25
  • @ThomasMDuBuisson, you can't make a type synonym an instance of a class. – dfeuer Mar 11 '16 at 21:26
  • @dfeuer Yes you can. Relax. :) – Ingo Mar 11 '16 at 23:16
  • 3
    In general you can use `TypeSynonymInstances` but that fails in this case since they must be fully saturated for instance declarations, and hence you can't make `B` itself an instance of anything only `B a` for some `a`, and that defeats the purpose... – sclv Mar 12 '16 at 00:44

2 Answers2

0

You already figured out the answer -- you just don't like it. There's no way to do what you're asking, since the only possible behavior is fixed by the signature of foldr.

The suggestion of a newtype newtype Flip t a b = Flip {unFlip :: (t b a)} with an appropriate instance defined is the most standard way to work around this, and now you can write your fold on a Flip Box instead of on a Box.

sclv
  • 38,665
  • 7
  • 99
  • 204
0

You must declare the instance as: instance Foldable Box where ... (Box a):: *