【问题标题】:A type constructor IS a monad or HAS a monad?类型构造函数是单子还是有单子?
【发布时间】:2018-01-13 11:49:27
【问题描述】:

人们通常说类型是单子。

在一些函数式语言和库(如 Scala/Scalaz)中,您有一个类型构造函数,如 List 或 Option,您可以定义一个与原始类型分离的 Monad 实现。所以基本上没有什么禁止你在类型系统中为同一个类型构造函数创建不同的 Monad 实例。


  • 类型构造函数可以有多个单子吗?
  • 如果是,您能提供任何有意义的例子吗?任何“人造”的?
  • 幺半群、应用程序呢...?

【问题讨论】:

  • Monad instances aren't unique。类型系统不允许一种类型有多个实例,但您可以使用 newtype 定义新实例。
  • 谢谢@Cubic。我会尝试阅读,但目前我对 Haskell 不太熟悉。这个问题与语言完全无关
  • 次要术语点:ListOption 不是类型,因为我们不能真正拥有例如def f(x: Option) = ...(我认为即使 Scala 也不允许这样做,但由于 JVM 的擦除,我不能 100% 确定)。只有例如List[Int], Option[Bool] 是类型。在 Haskell 中,我们称诸如 List,Option 类型构造函数之类的东西,具有类型 * -> *。在斯卡拉我不知道。事实上,对于像Int 这样的类型,我们并没有说它是一个 monad,而不是说它有一个 monad。对于List[Int],我们可以非正式地说,它是一元类型。
  • 感谢@chi 我编辑了问题

标签: scala haskell functional-programming language-agnostic category-theory


【解决方案1】:

你通常可以在数学中找到这一切。

  • monad 是一个三元组 (T, return, bind) 使得 (...)。当bindreturn 可以从上下文中推断出来时,我们只需将monad 称为T

  • 幺半群是一个三元组(M, e, •),使得 (...)。 (...) 我们只是将 monoid 称为 M

  • 拓扑空间是一对(S, T),使得(...)。我们只是将拓扑空间称为S

  • 环是一个元组(V, 0, +, 1, ×)...

确实,对于给定的类型构造函数T,可能有多个不同的returnbind 定义构成一个monad。为了避免每次都引用三元组,我们可以给 T 不同的名称来消除歧义,这与 Haskell 中的 newtype 构造相对应。例如:[] vs ZipListState s vs ReaderT s (Writer s)


附:说 monad 或 monoid 是三元组有些人为,特别是考虑到有不同的表示形式:我们也可以说 monad 是一个三元组(T, fmap, join),或者一个 monoid 是一对(M, •),与隐藏在额外条件中的标识元素(因为它是由 唯一确定的)。数学结构的本体是一个更哲学的问题,超出了 SO 的范围(以及我的专业知识之外)。但重新制定此类定义的更谨慎的方法可能是说“一个 monad 由三元组 (T, return, bind) (定义|表征)”。

【讨论】:

  • 感谢您的数学解释。您是否有任何示例,其中同一类型的构造函数有多个 monad?最好是一个实用且有用的例子,但如果不可能的话,“人造”的东西也会很有趣。
  • 我在上面给出了State sReaderT s (Writer s)的例子,它们都由函数s -> (s, a)组成。 ([]ZipList 是应用函子的示例,但 ZipList 不是 monad。)这个 Succs 类型有一个用于定义收缩的 monad 实例,但也有一个 product monad (Product Identity [])。
  • 如果您的字面意思是同一类型构造函数的 Monad 实例示例,那是不可能的,因为实例必须是唯一的。
  • 我不确定是否会关注这里。从 for a given type constructor T there may be multiple different definitions of return and bind that make a monad 我了解到,同一时间构造函数可以有 2 个实例。 (T, return1, bind1)(T, return2, bind2)
  • 数学,是的;但是在 Haskell 中,只能为给定类型定义一个 Monad 实例。但是,在 Haskell 中也有 newtype,允许我们用不同的名字来调用相同的类型;对于这个新名称,我们可以定义另一个 Monad 实例。 ZipList 是一个例子(只是它是 Applicative,不是 Monad,但原理相同)。
【解决方案2】:

就您所询问的语言使用而言,Google says that the phrase “has a monad” 似乎并不像您所询问的那样常用。大多数真实事件出现在诸如“Haskell 社区有一个单子问题”之类的句子中。然而,在野外确实存在一些模糊相似的用法,例如,“使它成为‘单子’的唯一原因是它有一个Monad 实例。”也就是说,monad 通常用作 monadic 的同义词,修饰其他一些名词以产生有时使用的短语(单子问题,Monad 实例)作为动词have的宾语。

关于编码:在Haskell中,一个类型可以声明Monad中的一个instanceMonoid中的一个等等。当一个给定的类型可以定义许多这样的实例时,例如数字如何在加法、乘法、最大值、最小值和许多其他操作下是幺半群时,Haskell 定义了单独的类型,例如Sum IntMonoid 实例超过Int其中操作为+Product Int,一个Monoid实例,其中操作为*

不过,我还没有全面检查数万次点击,因此很可能其中有更好的示例来说明您所询问的内容。

我经常看到的措辞就是我刚刚使用的措辞:type is category under一个操作

【讨论】:

    猜你喜欢
    • 2018-07-31
    • 2016-04-02
    • 2014-04-23
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 2014-11-28
    • 2018-06-06
    • 2019-02-20
    相关资源
    最近更新 更多