试图将一个包装类型的家族变成类似Functor的东西

Jac*_*tte 7 haskell

这是一个简单的示例,其中标识Functor运行良好:

newtype R a = R a

instance Functor R where
    fmap f (R a) = R $ f a
Run Code Online (Sandbox Code Playgroud)

但如果我添加一个中间类型的家庭,事情会变得很糟糕:

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)
Run Code Online (Sandbox Code Playgroud)

现在我无法将S变成Functor.我可以很容易地定义一类类似类似Functor的东西,但是我还需要一类类似Applicative和Monad的东西,这似乎是一条不愉快的道路.特别是

smap f (S a) = S $ f a
Run Code Online (Sandbox Code Playgroud)

实际上有我想要的类型,即smap :: (Sem a -> Sem b) -> S a -> S b.但是,当然,这不是Functor的类型.(当"相同"代码有两种不同的,不兼容的类型时,你不是只讨厌它吗?)

我已经探索过Data.Category.Functor以及Generics.Pointless.Functors,但似乎也没有完全解决我的问题. PointlessTypeFamilies似乎有更好的想法,但我仍然不确定如何得到足够类似Functor的东西.

已经醒悟过来了,即使该代码smap是相同的的fmapR,这是怎么回事略有不同.在某种程度上,如果我从了自然转化SemS,然后不知何故,我应该能够解除该获得smap.在那一点上,我想我不妨在这里问一下,这可能会给我带来很多麻烦!

Edw*_*ETT 3

当我遇到这样的情况时,我通常会改成这样:

data S b = forall a. S (a -> b) (Sem a)
Run Code Online (Sandbox Code Playgroud)

可以很容易地使之成为守法的Functor

instance Functor S where
  fmap f (S g s) = S (f . g) s
Run Code Online (Sandbox Code Playgroud)

或者我转向Coyoneda为我打包这种行为。