我知道一个单子是什么。 我想我已经正确地包裹着我的脑海围绕comonad是什么。 (或者说,什么是一个似乎很简单;棘手的部分是理解什么是关于这个有用的 ...)
我的问题是:什么能成为一个单子和 comonad?
我预见到两个可能的答案:
- 是的,这是常见的和广泛有用的。
- 不,他们这样做不同的工作会有任何理由想要的东西既。
所以,这是什么呢?
我知道一个单子是什么。 我想我已经正确地包裹着我的脑海围绕comonad是什么。 (或者说,什么是一个似乎很简单;棘手的部分是理解什么是关于这个有用的 ...)
我的问题是:什么能成为一个单子和 comonad?
我预见到两个可能的答案:
所以,这是什么呢?
是。 至于一些评论到一个答案:
newtype Identity a = Identity {runIdenity :: a} deriving Functor
instance Monad Identity where
return = Identity
join = runIdentity
instance CoMonad Identity where
coreturn = runIdentity
cojoin = Identity
Reader和Writer是精确的对偶,如图
class CoMonoid m where
comempty :: (m,a) -> a
comappend :: m -> (m,m)
--every haskell type is a CoMonoid
--that is because CCCs are boring!
instance Monoid a => Monad ((,) a) where
return x = (mempty,x)
join (a,(b,x)) = (a <> b, x)
instance CoMonoid a => CoMonad ((,) a) where
coreturn = comempty
cojoin = associate . first comappend
instance CoMonoid a => Monad ((->) a) where
return = flip (curry comempty)
join f = uncurry f . comappend
instance Monoid a => CoMonad ((->) a) where
coreturn f = f mempty
cojoin f a b = f (a <> b)
所述Cofree Comonad产生了用作单子和Comonads都是有用的一些数据结构:
data Cofree f a = a :< f (Cofree f a)
每Cofree Comonad通过备用仿函数产生一个单子 - 看到这里的实例:
http://hackage.haskell.org/packages/archive/free/3.4.1/doc/html/Control-Comonad-Cofree.html
instance Alternative f => Monad (Cofree f) where
return x = x :< empty
(a :< m) >>= k = case k a of
b :< n -> b :< (n <|> fmap (>>= k) m)
这给了我们,如非空列为单子和Comonads兼而有之(非空的F-分支树一起,等等)。
Identity
不是一种选择,而是Cofree Identity
产生无穷流,我们其实可以给不同的单子实例是流:
http://hackage.haskell.org/packages/archive/streams/3.1/doc/html/Data-Stream-Infinite.html
data Stream a = a :> Stream a
instance Comonad Stream where
duplicate = tails
extend f w = f w :> extend f (tail w)
extract = head
instance Monad Stream where
return = repeat
m >>= f = unfold (\(bs :> bss) -> (head bs, tail <$> bss)) (fmap f m)
(注意上述功能不在列表,但在代替定义streams
封装)。
类似地,读取器箭头不在替代,但Cofree ((->) r)
产生一个摩尔机,和Moore机器也是单子和comonads两者:
http://hackage.haskell.org/packages/archive/machines/0.2.3.1/doc/html/Data-Machine-Moore.html
data Moore a b = Moore b (a -> Moore a b)
instance Monad (Moore a) where
return a = r where r = Moore a (const r)
Moore a k >>= f = case f a of
Moore b _ -> Moore b (k >=> f)
_ >> m = m
instance Comonad (Moore a) where
extract (Moore b _) = b
extend f w@(Moore _ g) = Moore (f w) (extend f . g)
那么,什么是所有这些例子背后的直觉? 那么我们得到的comonadic操作是免费的。 我们拿到的单子操作一切形式的对角化。 随着替代,我们可以<|>
的东西放在一起,以“斯马什”的结构,而魔术了“空”当我们用完结构的东西,斯马什。 这让我们在有限的情况下工作。 由于缺乏替代,我们需要有结构的无限量,所以不管有多少“连接”的操作(这是我们能想到的作为剪接或替代),我们做,总是有更多的空间来放置拼接元素(如在希尔伯特酒店: http://www.encyclopediaofmath.org/index.php/Hilbert_infinite_hotel )。
与此相关, 每 Comonad产生了相关的单子(虽然我认为这更多的是好奇):
http://hackage.haskell.org/packages/archive/kan-extensions/3.1.1/doc/html/Control-Monad-Co.html
http://comonad.com/reader/2011/monads-from-comonads/
有许多都是一个有趣的结构Monad
和Comonad
。
该Identity
函子已在此间指出,通过其他几人,但也有不平凡的例子。
该Writer
Monad
扮演一个Reader
般的作用Comonad
。
instance Monoid e => Monad ((,) e)
instance Comonad ((,) e)
该Reader
Monad
扮演一个Writer
作为一个样的角色Comonad
。
instance Monad ((->) e)
instance Monoid e => Comonad ((->)e)
非空列表还形成两个单子和comonad和实际上涉及cofree comonads较大的建设的一个特例。 该Identity
的情况下也可以被看作是这种特殊情况。
也有各种各样的Yoneda
和Codensity
基于侃扩展式的结构,这项工作转变单子和comonads,虽然他们青睐的一个或另一个在操作效率方面。
我也有一个任意comonad转换成一个单子转换的适配器。 不幸的是相反的转换是不可能的在Haskell。
线性代数存在的概念双代数 。 理想的情况下,如果我们有形成既有一些Monad
和Comonad
,我们要使用这些操作起来没有对案件逐案基础上的推理,一个想有return
,并join
被Comonad余代数和扩展, extract
和duplicate
是Monad
代数。 如果这些条件成立,那么你就可以真正的原因大约有两码Monad f
和Comonad f
约束和混合从每个组合子,而不逐案的推理。
这取决于你认为什么是“单子”是。 如果你问“有可能是一种既实例Monad
和Comonad
一次?” 好的。 这里有一个简单的例子。
newtype Id a = Id a
instance Monad Identity where
return = Id
(Id a) >>= f = f a
instance Comonad Identity where
extract (Id a) = a
extend f ida = Id (f ida)
如果你的意思是数学,然后一个单子是三(X, return, bind)
,其中X
是一个类型, return
和bind
跟着你所期望的类型和法律。 类似地,comonad是(X, extend, extract)
。 我刚刚证明了X
S可能会发生相同,但是由于类型的extend
和return
或extract
,并bind
不同的它不可能对它们进行相同的功能。 所以数学单子永远是comonad。
扩大对锤的建议,它似乎很简单写一个函数[x] -> [[x]]
例如,
map (\ x -> [x])
会工作得很好。 所以它看起来像列表可以形成一个comonad。 啊,但等待。 这种处理cojoin
,但对于coreturn :: [x] -> x
? 这大概就是为什么只有非空列表形成comonad。
这给我们一个cobind功能与类型([x] -> x) -> [x] -> [x]
。 有趣的是,Hoogle知道没有这样的功能。 然而,我们已经有concatMap :: (x -> [x]) -> [x] -> [x]
。 我没有看到的cobind功能的立即使用,但我能想象一个存在。
我仍然在试图总结我的周围comonad的头脑和它可能是有用的。 答案至今已给了我一些思考......