7

下面是一个简单的例子,其中恒等函数运行良好:

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 类的东西,但是我还需要一类 Applicative-like 和 Monad-like,这似乎是一条不愉快的道路。特别是作为

smap f (S a) = S $ f a

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

我已经探索过Data.Category.FunctorGenerics.Pointless.Functors,但似乎也没有完全解决我的问题。 PointlessTypeFamilies似乎有更多好主意,但我仍然不确定如何从中获得足够类似 Functor 的东西。

我突然意识到,尽管 for 的代码与 for 的代码相同smap但发生的事情略有不同。在某种程度上,如果我有一个从to的自然转变,那么我应该能够以某种方式解除它以获得。那时我想我不妨在这里问一下,这样可能会为我省去不少麻烦!fmapRSemSsmap

4

1 回答 1

3

当我遇到这样的情况时,我通常会切换到类似的东西:

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为我打包这种行为。

于 2012-11-16T17:59:59.463 回答