试图将一个包裹类型的家庭变成一个Functor
以下是一个简单的例子,其中身份证明函数运作良好:
newtype R a = R a
instance Functor R where
fmap f (R a) = R $ f a
但如果我添加一个中间类型的家庭,事情会变得糟糕:
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)
现在我不能让S变成一个Functor。 我可以很容易地定义一类新的类似Functor的东西,但是我还需要一类类似Applicative的和Monad类的东西,这似乎是一条不愉快的道路。 尤其如
smap f (S a) = S $ f a
实际上有我想要的类型,即smap :: (Sem a -> Sem b) -> S a -> S b
。 但是,当然,这不是一个Functor的类型。 (当“相同”代码有两种不同的,不兼容的类型时,你难道不喜欢它吗?)
我已经探索Data.Category.Functor以及Generics.Pointless.Functors,但似乎也无法解决我的问题。 PointlessTypeFamilies似乎有更好的想法,但我仍然不确定如何获得足够类似Functor的东西。
虽然smap
的代码与R
的fmap
的代码相同,但是发生的事情略有不同。 在某种程度上,如果我从Sem
到S
发生了自然变化,那么我应该能够提升它以获得smap
。 那时候,我觉得我不妨在这里问一下,这可以为我节省很多麻烦!
当我遇到像这样的情况时,我通常会切换到如下所示的状态:
data S b = forall a. S (a -> b) (Sem a)
它可以很容易地变成一个守法的Functor
instance Functor S where
fmap f (S g s) = S (f . g) s
或者我转向Coyoneda
来为我打包这种行为。
上一篇: Trying to make a wrapped type family into a something Functor