Trying to make a wrapped type family into a something Functor

Here is a simple example where the identity Functor works well:

newtype R a = R a

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

but if I add an intermediate type family, things get wonky:

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't make S into a Functor. I can easily define a new class of Functor-like things, but then I will also need a class of Applicative-like and Monad-like, and that seems like an unhappy road. Especially as

smap f (S a) = S $ f a

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

I have explored Data.Category.Functor as well as Generics.Pointless.Functors, but neither seemed to quite solve my problem either. PointlessTypeFamilies seemed to have further good ideas, and yet I am still unsure how to get something sufficiently Functor-like out of this.

It has dawned onto me that even though the code for smap is identical to that of fmap for R , what is going on is slightly different. In a way, if I had a natural transformation from Sem to S , then somehow I ought to be able to lift that to obtain smap . At that point, I figured I might as well ask here, that might save me quite a bit of trouble!


When I encounter a situation like this I usually switch to something like:

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

which can easily be made into a law-abiding Functor

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

or I turn to Coyoneda to package up that behavior for me.

链接地址: http://www.djcxy.com/p/11432.html

上一篇: 手动创建不适用于应用程序的字符串资源文件

下一篇: 试图将一个包裹类型的家庭变成一个Functor