在之前的回答中,Petr PudlakCFunctor
为除从Hask到Hask的函子之外的函子定义了该类。使用类型族重新编写它,它看起来像
class CFunctor f where
type Dom f :: * -> * -> * -- domain category
type Cod f :: * -> * -> * -- codomain category
cmap :: Dom f a b -> Cod f (f a) (f b) -- map morphisms across categories
看起来像的实例,例如
instance CFunctor Maybe where
type Dom Maybe = (->) -- domain is Hask
type Cod Maybe = (->) -- codomain is also Hask
cmap f = \m -> case m of
Nothing -> Nothing
Just x -> Just (f x)
在范畴论中,只要F : C --> D是函子且G : D --> E是函子,则组合GF : C --> E也是函子。
我想用 Haskell 来表达这一点。因为我不会写instance CFunctor (f . g)
,所以我介绍一个包装类:
newtype Wrap g f a = Wrap { unWrap :: g (f a) }
在写这个CFunctor
实例时,我得到了
instance (CFunctor f, CFunctor g, Cod f ~ Dom g) => CFunctor (Wrap g f) where
type Dom (Wrap g f) = Dom f
type Cod (Wrap g f) = Cod g
cmap = undefined
但我无法弄清楚cmap
应该是什么。有什么建议吗?
PS这一切的最终原因是还引入了一个Adjunction
带有方法的类unit
and counit
,然后自动从附属词中派生monad实例。但首先,我需要向编译器展示两个仿函数的组合也是一个仿函数。
我知道我可以cmap.cmap
在类型的对象上使用g (f a)
它并且会起作用,但这看起来有点像作弊 - 当然函子只是一个函子,编译器不必知道它实际上是两个的组合其他函子?