Dan*_*Dos 6 haskell functor applicative comonad
回忆一下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
Run Code Online (Sandbox Code Playgroud)
尽管目前尚不清楚如何用(数学)范畴论来表达此类,但当定义以下函数时,情况就会变得清晰:
liftZ2 :: Applicative f => (f a, f b) -> f (a, b)
liftZ2 (x, y) = liftA2 (,) x y
Run Code Online (Sandbox Code Playgroud)
在这里,(,)应该可以被识别为分类产品。用余积替换积并反转所有箭头给出以下类别:
class Functor f => Coapplicative f where
copure :: f a -> a
coliftZ2 :: f (Either a b) -> Either (f a) (f b)
Run Code Online (Sandbox Code Playgroud)
一些实例:
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)
Run Code Online (Sandbox Code Playgroud)
我有一种强烈的直觉,它Coapplicative是 的超类Comonad,但我不知道如何证明它。另外,是否有Coapplicative一个不是 的实例Comonad?
这不是一个完整的答案,但我至少可以证明您的实例Coapplicative NonEmpty不能Comonad单独从方法派生;也就是说,如果有一些参数化的实现
coliftZ2 :: (Comonad w) => w (Either a b) -> Either (w a) (w b)
Run Code Online (Sandbox Code Playgroud)
那么它不会生成您的实例NonEmpty。这是因为单独的方法Comonad NonEmpty无法为我们提供任何更改列表长度的方法,但您的NonEmpty实例会coliftZ2更改长度。因此,如果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)
Run Code Online (Sandbox Code Playgroud)
并考虑其coliftZ2实施必须是什么。你还没有给出任何法律Coapplicative,但如果你这样做了,我会把钱花在打破这些法律上,因为没有任何实现coliftZ2是令人满意的对称的。下面的两个方程都相当牵强,但它们似乎表明了非常不同的操作意图:
coliftZ2 (Two (Left x) (Left y)) = Left (Two x y)
coliftZ2 (Two (Left x) (Right _)) = Left (Two x x)
Run Code Online (Sandbox Code Playgroud)
在我看来,最能阐明这一点的问题是:我们应该对与 comonad 方法的关系有何期望?coliftZ2