Consider the data type
data Foo f = Foo {fooInt :: f Int, fooBool :: f Bool}
I would like a function mapFoo :: (forall a. f a -> g a) -> Foo f -> Foo g
. My options:
Foo
to gain fields over time and I want that to be as frictionless as possible, so having to add a case to this function is annoying.Generic
, but when I tried to implement the K1
case (specifically to handle Rec0
) I couldn't figure out how to do it; I needed it to change the type.If there is a generic way to write mapFoo
without reaching for Template Haskell, I'd love to know about it! Thanks.
The rank2classes
package can derive this for you.
{-# LANGUAGE TemplateHaskell #-}
import Rank2.TH (deriveFunctor)
data Foo f = Foo {fooInt :: f Int, fooBool :: f Bool}
$(deriveFunctor ''Foo)
Now you can write mapFoo = Rank2.(<$>)
.