这是对我上一个问题的答案的后续跟进.
假设我需要映射每个项目a:A
的List[A]
来b:B
使用功能def f(a:A, leftNeighbors:List[A]): B
和产生List[B]
.
显然,我不能只是map
在列表上调用,但我可以使用列表拉链.拉链是一个在列表中移动的光标.它提供对当前element(focus
)及其邻居的访问.
现在我可以替换我f
的 def f'(z:Zipper[A]):B = f(z.focus, z.left)
并将这个新函数传递f'
给cobind
方法Zipper[A]
.
这样的cobind
工作:它f'
用拉链调用,然后移动拉链,f'
用新的 "移动"拉链调用,再次移动拉链等等......直到拉链到达列表的末尾.
最后,cobind
返回一个新的拉链类型Zipper[B]
,可以将其转换为列表,从而解决问题.
现在请注意之间的对称性cobind[A](f:Zipper[A] => B):Zipper[B]
和bind[A](f:A => List[B]):List[B]
这就是为什么List
是Monad
和Zipper
是Comonad
.
是否有意义 ?
Haskell中的Comonad类型类是什么?作为Comonad从Control.Comonad在comonad包(即提供Comonad类型类也是任何其他包的说明欢迎).我模糊地听说过Comonad,但我真正知道的是它提供的extract :: w a -> a
,与Monad相似return :: a -> m a
.
在"真实"代码中注意Comonad的"真实生活"用途的奖励积分.
给定任何容器类型,我们可以形成(以元素为中心的)Zipper并且知道这个结构是Comonad.最近在针对以下类型的另一个Stack Overflow问题中详细探讨了这个问题:
data Bin a = Branch (Bin a) a (Bin a) | Leaf a deriving Functor
Run Code Online (Sandbox Code Playgroud)
使用以下拉链
data Dir = L | R
data Step a = Step a Dir (Bin a) deriving Functor
data Zip a = Zip [Step a] (Bin a) deriving Functor
instance Comonad Zip where ...
Run Code Online (Sandbox Code Playgroud)
这是一个情况Zip
是Comonad
,虽然它的实例的建设是一个有点毛.也就是说,Zip
可以完全机械地衍生出来Tree
并且(我相信)任何以这种方式衍生的类型都是自动的Comonad
,所以我觉得应该是这样我们可以通用和自动地构造这些类型及其组合.
实现拉链构造的一般性的一种方法是使用以下类和类型族
data Zipper t a = Zipper { diff :: D t a, here …
Run Code Online (Sandbox Code Playgroud) 使用类型级自然的典型定义,我已经定义了一个n维网格.
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
data Nat = Z | S Nat
data U (n :: Nat) x where
Point :: x -> U Z x
Dimension :: [U n x] -> U n x -> [U n x] -> U (S n) x
dmap :: (U n x -> U m r) -> U (S n) x -> U (S m) r
dmap f (Dimension ls mid …
Run Code Online (Sandbox Code Playgroud) 有一些想法的Comonad类型类是在Haskell什么,我听说过的商店comonad.但是看看Control.Comonad.Store.Lazy,我真的不明白.这是什么意思?它是为了什么?我听说过Store = CoState,State Monad的双重身份.那是什么意思?
是否有带签名的内置功能:: (Monad m) => m a -> a
?
Hoogle告诉我们没有这样的功能.
你能解释一下原因吗?
我一直在玩Cofree
,并且不能完全理解它.
例如,我想Cofree [] Num
在ghci中玩,并且不能得到任何有趣的例子.
例如,如果我构造一个Cofree类型:
let a = 1 :< [2, 3]
Run Code Online (Sandbox Code Playgroud)
我希望extract a == 1
,但我得到这个错误:
No instance for (Num (Cofree [] a0)) arising from a use of ‘it’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Run Code Online (Sandbox Code Playgroud)
还有一种:
extract a :: (Num a, Num (Cofree [] a)) => a
Run Code Online (Sandbox Code Playgroud)
我可以得到一些简单的例子,甚至是琐碎的,如何使用Cofree有,比方说,函子:[]
,或者Maybe
,或者Either
,演示
extract
extend
unwrap
duplicate
?Cross发布:https: …
好吧,让我们说你有类型
newtype Dual f a = Dual {dual :: forall r. f(a -> r)->r}
Run Code Online (Sandbox Code Playgroud)
事实证明,什么时候f
是Comonad,Dual f
是Monad(有趣的运动).它是否相反?
您可以定义fmap ab (Dual da) = Dual $ \fb -> da $ fmap (. ab) fb
和extract (Dual da) = da $ return id
,但我不知道如何定义duplicate
或extend
.
这甚至可能吗?如果没有,那么证据不存在(是否有一个特定的Monad m
,你可以证明Dual m
它不是一个comonad)?
一些观察:
Dual IO a
基本上Void
(并且Const Void
是有效的Comonad
).
Dual m a
为MonadPlus m
是 Void
(只使用dual mzero
). …
我想把二叉树拉链作为comonad的一个实例,但我无法弄清楚如何duplicate
正确实现.
这是我的尝试:
{-# LANGUAGE DeriveFunctor #-}
import Data.Function
import Control.Arrow
import Control.Comonad
data BinTree a
= Leaf a
| Branch a (BinTree a) (BinTree a)
deriving (Functor, Show, Eq)
data Dir = L | R
deriving (Show, Eq)
-- an incomplete binary tree, aka data context
data Partial a = Missing Dir (BinTree a) a
deriving (Show, Eq, Functor)
-- BTZ for BinTree Zipper
newtype BTZ a = BTZ { getBTZ :: ([Partial a], BinTree a) }
deriving …
Run Code Online (Sandbox Code Playgroud)