haskell 这个“Coapplicative”类是Comonad的超类吗?

dpiehjr4  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(123)

回想一下Applicative类:

class Functor f => Applicative f where
    pure :: a -> f a
    liftA2 :: (a -> b -> c) -> f a -> f b -> f c
    (<*>) :: f (a -> b) -> f a -> f b

    liftA2 h x y = fmap h x <*> y
    (<*>) = liftA2 id

虽然还不清楚如何用(数学)范畴论来表达这个类,但当定义以下函数时,它就变得清晰了:

liftZ2 :: Applicative f => (f a, f b) -> f (a, b)
liftZ2 (x, y) = liftA2 (,) x y

在这里,(,)应该被识别为分类产品。将乘积替换为余积并反转所有箭头,得到以下类:

class Functor f => Coapplicative f where
    copure :: f a -> a
    coliftZ2 :: f (Either a b) -> Either (f a) (f b)

一些示例:

import Data.Functor.Identity
import qualified Data.List.NonEmpty as NonEmpty
import Data.Either

instance Coapplicative Identity where
    copure (Identity x) = x
    coliftZ2 (Identity (Left x)) = Left (Identity x)
    coliftZ2 (Identity (Right y)) = Right (Identity y)

instance Coapplicative NonEmpty.NonEmpty where
    copure (x NonEmpty.:| _) = x
    coliftZ2 (Left x NonEmpty.:| xs) = Left (x NonEmpty.:| lefts xs)
    coliftZ2 (Right y NonEmpty.:| ys) = Right (y NonEmpty.:| rights ys)

instance Coapplicative ((,) e) where
    copure (_, x) = x
    coliftZ2 (e, Left x) = Left (e, x)
    coliftZ2 (e, Right y) = Right (e, y)

instance Monoid m => Coapplicative ((->) m) where
    copure f = f mempty
    coliftZ2 f = case copure f of
        Left x -> Left (fromLeft x . f)
        Right y -> Right (fromRight y . f)

我有一种强烈的直觉,CoapplicativeComonad的超类,但我不知道如何证明这一点。另外,是否存在不是ComonadCoapplicative示例?

ckocjqey

ckocjqey1#

这不是一个完整的答案,但我至少可以说明Coapplicative NonEmpty的示例不能单独从Comonad方法派生;也就是说,如果存在

coliftZ2 :: (Comonad w) => w (Either a b) -> Either (w a) (w b)

那么它不会为NonEmpty生成示例。这是因为Comonad NonEmpty的方法本身并不能改变列表的长度,但是coliftZ2NonEmpty示例改变了列表的长度。因此,如果NonEmpty要成为Coapplicative,它必须以其他方式这样做,否则Coapplicative不能是Comonad的超类。
当你进一步调查,我会说这是值得探讨的comonad

data Two a = Two a a
    deriving (Functor)

instance Comonad Two where
    extract (Two x _) = x
    duplicate (Two x y) = Two (Two x y) (Two y x)

并考虑其coliftZ2实现必须是什么。你还没有给出Coapplicative的任何定律,但是如果你有,我会把我的钱放在打破它们上,因为没有coliftZ2的实现是令人满意的对称的。以下两个等式都是相当强迫的,但它们似乎表明了非常不同的操作意图:

coliftZ2 (Two (Left x) (Left y)) = Left (Two x y)
coliftZ2 (Two (Left x) (Right _)) = Left (Two x x)

在我看来,最能说明这一点的问题是:我们应该期待coliftZ2与comonad方法的 * 关系 * 是什么?

相关问题