Problem:
I recently asked the following question: ask how to create a common mapping function, and a common instance Functorfor any arbitrary polymorphic ADT (such as algebraic data), such as lists, trees, etc .:Functor instance for common polymorphic ADT in Haskell?
Now I am trying to reformulate the above to be compatible with recursion-schemes. Those. instead of defining the base functor, and then define the type as its fixed point, I want to define the type on the one hand, the basic functor on the other and match them using the family type Base.
So instead:
data ListF a b = NilF | ConsF a b
newtype Fix f = Fix { unFix :: f (Fix f) }
type List a = Fix (ListF a)
I want to do this:
data ListF a b = NilF | ConsF a b
data List a = Nil | Cons a (List a)
type instance Base (List a) = ListF a
recursion-schemes, fmap . , , "" , .
:
Bifunctor - Base. a :~: b Data.Type.Equality. , :
{-
import Data.Bifunctor
import Data.Functor.Foldable
import Data.Type.Equality
gmap :: (Bifunctor p, Foldable (f a), Unfoldable (f b)) =>
(forall x. p x :~: Base (f x)) -> (a -> b) -> f a -> f b
gmap refl f = cata alg
where
alg = embed .
castWith (apply refl Refl) .
bimap f id .
castWith (apply (sym refl) Refl)
Functor. , .
Equals - :
instance (Bifunctor p, Foldable (f a), Unfoldable (f b), Equals (p a) (Base (f a)))
=> Functor f where
, , (, , gmap ).
, gmap SO-:
gmap :: (Bifunctor f) => (a -> b) -> Fix (f a) -> Fix (f b)
gmap f = unwrapFixBifunctor . cata alg . wrapFixBifunctor
where
alg = Fix . bimap f id
unwrapFixBifunctor :: (Bifunctor f) => Fix (WrappedBifunctor f a) -> Fix (f a)
unwrapFixBifunctor = Fix . unwrapBifunctor . fmap unwrapFixBifunctor . unFix
wrapFixBifunctor :: (Bifunctor f) => Fix (f a) -> Fix (WrappedBifunctor f a)
wrapFixBifunctor = Fix . fmap wrapFixBifunctor . WrapBifunctor . unFix
:
, gmap - :
gmap :: (Foldable t, Unfoldable d, Bifunctor p, Base d ~ p b, Base t ~ p a)
=> (a -> b) -> t -> d
gmap f = cata ( embed . bimap f id )
, Functor,