Haskell 共形复制函数
为什么定义函数复制 对于Comonad typeclass(),您必须修改“上下文中”的所有元素(即更改上下文当前值以外的元素)。为什么不在Monad中使用类似return的东西呢 示例(拉链): 为什么我不能将复制定义为Haskell 共形复制函数,haskell,comonad,Haskell,Comonad,为什么定义函数复制 对于Comonad typeclass(),您必须修改“上下文中”的所有元素(即更改上下文当前值以外的元素)。为什么不在Monad中使用类似return的东西呢 示例(拉链): 为什么我不能将复制定义为 duplicate z = Z [] z [] 我试图从Comonad规则中推导出复制函数的需求,但最终我总是得到一个复制函数,它将元素包装得很像monad中的一个return,而不需要做任何其他事情 有人说: 重复的有点难理解。从列表拉链,我们必须建立一个
duplicate z = Z [] z []
我试图从Comonad规则中推导出复制函数的需求,但最终我总是得到一个复制函数,它将元素包装得很像monad中的一个return,而不需要做任何其他事情
有人说:
重复的有点难理解。从列表拉链,我们必须建立一个列表拉链的列表拉链。这背后的含义(由每个实例必须满足的comonad定律确认)是,在复制结构中移动会返回原始结构,并通过相同的移动进行更改
但我不明白为什么一定是这样。Comonad规则中的fmap始终应用于已包装的元素,之后这一个元素始终使用extract“展开”,除了包装duplicate的参数,为什么还要在duplicate函数中做其他事情呢
你能指出我遗漏了什么吗?我觉得我在某个地方犯了一些明显的错误,但我就是不能自己去弄清楚
提前感谢您的回复 如果您可以对该类型执行其他操作,而不仅仅是从中提取
,这一点很重要。直观地说,如果您只能提取值,那么类型只保存一个值,因此复制一个值就是复制所有内容。这在一般情况下是不正确的,对于拉链也是不正确的
Comonad
法则只是wa->b类型函数的伪装类别法则。因为这些都来自于类别,所以用一个类别来解释它们可能比用Comonad
法则来解释它们更容易<代码>提取
是该类别的标识,是合成运算符
-- | Right-to-left 'Cokleisli' composition
(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c
f =<= g = f . extend g
这看起来很容易解释。现在,让我们为您的Z
类型配备另一个我们可以讨论的函数isFirst
仅当Z
表示列表中某个位置的值之前没有任何内容时才会返回true
isFirst :: Z a -> Bool
isFirst (Z [] _ _) = True
isFirst _ = False
现在,让我们考虑当我们使用<代码>第一个< /代码>三类法则时会发生什么。唯一两个似乎立即适用于它的是
extract
是由=组成的左右标识。您可能会对这个问题感兴趣,这个问题是关于为任何可微类型导出拉链的comonad实例。如果是这样的话,请查看pigworker的偏微分方程广泛解或我的二阶导数解。感谢链接,我在试图找到我问题的答案时滚动了它,但现在当你明确推荐它时,我发现它有很多新东西需要我思考。我一定会调查的嗨Cirdec你搞定了。我自己也试图提出一个反例,但我总是以焦点为目标,从未尝试过查询上下文(就像您的isFirst
所做的那样)。这不仅是正确的答案,而且还包含了有关该主题的更多有用信息。将投票和评分作为接受答案。
-- | Right-to-left 'Cokleisli' composition
(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c
f =<= g = f . extend g
f =<= g = f . fmap g . duplicate
isFirst :: Z a -> Bool
isFirst (Z [] _ _) = True
isFirst _ = False
extract =<= isFirst $ Z [1] 2 []
extract . fmap isFirst . duplicate $ Z [1] 2 []
extract . fmap isFirst $ Z [] (Z [1] 2 []) []
extract $ Z [] (isFirst (Z [1] 2 [])) []
extract $ Z [] False []
False
isFirst =<= extract $ Z [1] 2 []
isFirst . fmap extract . duplicate $ Z [1] 2 []
isFirst . fmap extract $ Z [] (Z [1] 2 []) []
isFirst $ Z [] (extract (Z [1] 2 [])) []
isFirst $ Z [] 2 []
True
z = (=<= extract) z
z = fmap extract . duplicate $ z
Z left x right = fmap extract . duplicate $ Z left x right
Z left x right = fmap extract $ Z lefts (Z l x' r) rights
Z left x right = Z (fmap extract lefts) (extract (Z l x' r)) (fmap extract rights)
left = fmap extract lefts
x = extract (Z l x' r)
right = fmap extract rights