Trying to turn a family of wrapped types into something like Functor-like

Here is a simple example where a Functor personality works well:

newtype R a = R a instance Functor R where fmap f (R a) = R $ fa 

but if I add a family of intermediate type, everything becomes unstable:

 data IntT data a :-> b type family Sem a :: * type instance Sem IntT = Int type instance Sem (a :-> b) = Sem a -> Sem b newtype S a = S (Sem a) 

and now I can not do S in Functor. I can easily define a new class of Functor-like things, but then I will also need the Applicative-like and Monad-like classes, and that seems like an unfortunate road. Especially since

 smap f (S a) = S $ fa 

really has the type that I want, namely smap :: (Sem a -> Sem b) -> S a -> S b . But of course, this is not the type of Functor. (Don't you just hate it when the "same" code has 2 different, incompatible types?)

I researched Data.Category.Functor as well as Generics. Pointless.Functors , but none of them seemed to solve my problem either. PointlessTypeFamilies seemed to have additional good ideas, and yet I'm still not sure how Functor can draw anything from this.

It became clear to me that although the code for smap is identical to the fmap code for R , it happens a little differently. In a way, if I had a natural conversion from Sem to S , then somehow I would have to pick it up to get a smap . At that moment, I thought I could ask here what could save me from trouble!

+7
source share
1 answer

When I come across this situation, I usually switch to something like:

 data S b = forall a. S (a -> b) (Sem a) 

which can easily be turned into a regular Functor

 instance Functor S where fmap f (S gs) = S (f . g) s 

or I go to Coyoneda to pack this behavior for me.

+3
source

All Articles