3

rank2classes包提供一个版本,Functor其映射函数似乎是类型构造函数之间的自然转换。

按照这个想法,这是 2 级版本Bifunctor

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneKindSignatures #-}
import Data.Kind

type Rank2Bifunctor :: ((Type -> Type) -> (Type -> Type) -> Type) -> Constraint
class Rank2Bifunctor b where
  rank2bimap ::
    (forall x. p x -> p' x) -> (forall x. q x -> q' x) -> b p q -> b p' q'

似乎很清楚,Foo可以给这种类型一个Rank2Bifunctor实例:

data Foo f g = Foo (f Int) (g Int)

instance Rank2Bifunctor Foo where
    rank2bimap tleft tright (Foo f g) = Foo (tleft f) (tright g)

但是Bar这种嵌套f和的类型呢g

data Bar f g = Bar (f (g Int))

对于初学者来说,似乎我们需要Functor p在 , 的签名中要求rank2bimap能够转换.gf

Bar有效的“rank-2 双函子”吗?

4

1 回答 1

2

事实上,这不是你的一个实例Bifunctor,因为缺乏约束允许你选择一个逆变函子 forf然后rank2bimap大致相当于实现fmapfor f

rank2bimap id :: (g ~> g') -> Bar f g -> Bar f g'  -- covariance of f, kinda (since Bar f g = f (g Int))

type f ~> f' = (forall x. f x -> f' x)

如果您添加fand g(此处为可选)是函子的要求,那么您确实得到了一个双函子:

rank2bimap :: (Functor f, Functor g) => (f ~> f') -> (g ~> g') -> Bar f g -> Bar f' g'

特别是,要证明双函子定律,您将需要 的自由定理f ~> f',假设ff'是函子,然后n :: f ~> f'满足所有phi, fmap phi . n = n . fmap phi

于 2021-02-04T15:06:13.523 回答