假设的理解:协变函子和逆变函子之间的区别,以及延伸而来的双函子和泛函子之间的区别
摘要:您想要一个适用且可替代的双函子,或者一个从可整除到可替代的函子,具体取决于它是双函子还是函子
函子 f 可以采用 'f' 的关联对(又名积、元组)并返回对的 f,被称为 applicative(嗯,它是来自 'semigroupoids' 的 Apply 类型类,applicatives 也需要一个单位)
也就是说,f配备:
pair :: f a -> f b -> f (a,b)
pair = liftA2 (,)
pairUnit :: f ()
pairUnit = pure ()
选择的等效项(也称为求和)与替代函子类似地相关(它是“semigroupoids”中的 Alt 类型类):
pick :: f a -> f b -> f (Either a b)
pick fa fb = fmap Left fa <|> fmap Right fb
pickUnit :: f Void
pickUnit = empty
关于应用和替代(无单位)的这两种表述值得注意的是,它们并不是整个故事:还有逆变应用函子和逆变替代函子,它们分别是来自“逆变”的 Divisible 和 Decidable 类型类
应用函子知道如何将部分组合成整体,可分函子知道如何将整体分割成部分
pairCovariant :: ((a,b) -> c) -> f a -> f b -> f c
pairCovariant f fa fb = fmap f (pair fa fb)
-- liftA2 f = pairCovariant (curry f)
-- this is also called 'divide'
pairContravariant :: (c -> (a,b)) -> f a -> f b -> f c
pairContravariant f fa fb = contramap f (pair fa fb)
-- given an inhabitant of a, provide an f a
pure :: a -> f a
pure a = fmap (const a) . pairUnit
-- this is also called 'conquer'
emptyPair :: f a
emptyPair = fmap (const ()) . pairUnit
(请注意pair和zip之间的相似性,以及pairCovariant和zipWith - 它们在不同的服装中是相同的功能,其中zip和zipWith描述了应用列表的ZipList解释)
替代函子知道如何将选项组合成一个整体,可判定函子知道如何将整体拆分为选项
pickCovariant :: (Either a b -> c) -> f a -> f b -> f c
pickCovariant f fa fb = fmap f (pick fa fb)
-- aka choose
pickContravariant :: (c -> Either a b) -> f a -> f b -> f c
pickContravariant f fa fb = contramap f (pick fa fb)
empty :: f a
empty = fmap absurd . pickUnit
-- given proof a is uninhabited, provide an f a
-- aka lose
pureChoice :: (a -> Void) -> f a
pureChoice a = contramap a . pureUnit
所以你希望第一个参数是可应用的/可整除的,第二个参数是可替代的/可判定的,这取决于每个参数的协变/逆变
换句话说:如果它是双函子,则适用且可替代;如果它是泛函数,则可整除且可替代
这里的想法总结:
applicative、alternative(无 applicative 超类)、可整除和可判定函子都是同一事物的所有版本,通过在对和选择之间进行选择以及协/逆变而制成
又名,应用程序是成对的单流协变函子,替代品是选择的单流逆变函子,等等
进一步阅读:
- 关于此处描述的应用族:https://duplode.github.io/posts/divisible-and-the-monoidal-quartet.html https://duplode.github.io/posts/divisible-and-the-monoidal-quartet.html
- 可整除的函子 -> 适用的:https://hackage.haskell.org/package/product-profunctors https://hackage.haskell.org/package/product-profunctors