当前位置: 首页 > 知识库问答 >
问题:

一个非平凡的comonoid长什么样?

齐思淼
2023-03-14

经过稍加搜索,我找到了一个StackOverflow的答案,它用comonoids必须满足的定律更好地解释了这一点。所以我想我明白了为什么在Haskell中只有一个假设的Comonoid类型的可能实例

因此,要找到一个非平凡的comonoide,我想我们必须从其他类别中寻找。当然,如果范畴理论家有一个comonoids的名字,那么有一些有趣的。该页上的其他答案似乎暗示了一个涉及supply的示例,但我找不出一个仍然满足这些规律的答案。

我还转到Wikipedia:有一个关于monoid的页面没有引用类别理论,在我看来,这是对Haskell的monoidtypeclass的充分描述,但“comonoid”重定向到对monoid和comonoid的类别理论描述,我无法理解,而且似乎仍然没有任何有趣的例子。

  1. 同子类可以用类似单子类的非范畴理论术语来解释吗?
  2. 有趣的comonoid的一个简单示例是什么,即使它不是Haskell类型?(在熟悉的Haskell Monad之上,还能在Kleisli类别中找到一个吗?)

编辑:我不确定这是否真的是类别理论上的正确,但我在问题2的括号中想象的是delete::a->m()split::a->m(a,a)对于一些特定的Haskell类型a和Haskell单元体m的非平凡定义,它们满足链接答案中comonoid定律的Kleisli-arrow版本。comonoids的其他例子仍然是受欢迎的。

共有1个答案

张卓
2023-03-14

正如Phillip JF所提到的,在子结构逻辑中谈论comonoid是很有趣的。我们来谈谈线性λ微积分。这很像您的普通类型的λ演算,除了每个变量必须使用一次。

为了获得一种感觉,让我们数一下给定类型的线性函数,即。

a -> a

只有一个居民,ID。而

(a,a) -> (a,a)
(a, b) ↦ (a, a)
(a, b) ↦ (b, b)
(a, b) ↦ (a, b)
(a, b) ↦ (b, a)
data File
open  :: String -> File
close :: File   -> ()      -- consumes a file, but we're ignoring purity right now
t1    :: File -> File
t2    :: File -> File
close . t1 . t2 . open
close . t2 . t1 . open
close . t1      . open
close . t2      . open
let f1 = open "foo"
    f2 = t1 f1
    f3 = t2 f1
in close f3

因为我们使用了两次f1

现在,您可能想知道什么东西必须遵循线性规则。例如,我决定一些管道不必同时包含T1T2(比较前面的枚举练习)。此外,我还介绍了openclosehtml" target="_blank">函数,它们愉快地创建和销毁file类型,尽管这违反了线性。

实际上,我们可能会假设存在违反线性的函数--但并非所有客户机都可能。这很像io单子--所有的秘密都存在于io的实现中,因此用户可以在一个“纯粹”的世界中工作。

class Comonoid m where
  destroy :: m -> ()
  split   :: m -> (m, m)

在线性lambda演算中实例化comonoid的类型是一种具有携带破坏和复制规则的类型。换句话说,这是一种完全不受线性λ演算约束的类型。

由于Haskell根本没有实现线性lambda演算规则,所以我们总是可以实例化comonoid

instance Comonoid a where
  destroy a = ()
  split a   = (a, a)

或者,从另一种角度来看,Haskell是一个线性LC系统,它只是碰巧为每个类型实例化comonoid,并自动为您应用destroysplit

 类似资料:
  • [basic.def.odr]/3引用了术语“非平凡函数”,我在标准(N4140)中找不到它的定义。 [basic.def.odr]/3 除非将左值-右值转换(4.1)应用于x会产生一个不调用任何重要函数的常量表达式(5.19),并且如果x是一个对象,ex是表达式e的一组潜在结果的元素,其中左值-右值转换(4.1)应用于e,或者e是一个丢弃的值表达式(第5条)。

  • 问题内容: 我需要使用这种结构将一些数据库表的内容转储到XML文件中 每个表在未知状态下的真实记录数,因此我无法将单个表的所有数据存储在内存中并转储到XML。 我的工作现在定义为: 这项工作不完整,无法满足我的需求,因为输出看起来像 我认为我必须丰富作家和/或编组人员的组件才能实现我的目标,但我还没有找到继续前进的好方法:( 我的问题是: 如何按照开始时所述构建复杂的XML结构,并使作业完全可重新

  • 我正在尝试编写一个工厂函数来创建闭包,用作gstreamer中的“pad回调”。我已经提供了一个精简的例子,它应该可以在安装了gstreamer机箱和gstreamer二进制文件/插件的情况下编译。 通过我的研究,我使用了“impl-trait”方法,而不是装箱,使工厂函数工作。不过,我想找出装箱方法,因为它在某些情况下似乎更合适。 这是我得到的最接近。通过使用“Box”取消标记为<code>Cl

  • 我希望有一个类型特征,对于任何在使用前不需要内存初始化的类型返回true,并且其复制构造函数可以作为memcpy实现。 我想让它回到真实 < li >整数类型(char、short int、int、long int等) < li >浮点数类型(float,double) < li>il::array (il::array是我自己对std::array的实现)for T是int、double、il:

  • 当锁被释放后,任何一个线程都有机会竞争得到锁,这样做的目的是提高效率,但缺点是可能产生线程饥饿现象。

  • 我知道POD类可以安全地设置。在c 17(?)std::is\U pod被std::is\U标准布局和std::is\U琐碎取代。如果一个非平凡但标准的布局结构只包含char[]数据和一个用户定义的构造函数,那么它可以安全地被memset吗。 具有数十个char[]成员变量的遗留类。 现有代码在使用对象时只对其执行memset。 我想在更新的结构B上调用用户定义的构造函数,因为除了“0”之外,还有