你把包裹在单子里的数据叫做啥?
Posted
技术标签:
【中文标题】你把包裹在单子里的数据叫做啥?【英文标题】:What do you call the data wrapped inside a monad?你把包裹在单子里的数据叫做什么? 【发布时间】:2014-07-30 09:37:57 【问题描述】:在演讲和写作中,我一直想引用 monad 中的数据,但我不知道该怎么称呼它。
例如,在 Scala 中,传递给 flatMap
的函数的参数被绑定到......呃...... monad 中的那个东西。在:
List(1, 2, 3).flatMap(x => List(x, x))
x
被绑定到我无话可说的那个东西上。
有点复杂,传递给 Kleisli 箭头的参数不一定会绑定到 all monad 内的数据。对于 List
、Set
、Stream
和许多其他 monad,flatMap
多次调用 Kleisli 箭头,每次将 x
绑定到 monad 内的不同数据片段。或者甚至可能不是“数据”,只要遵循单子定律。不管它是什么,它都被包裹在 monad 中,flatMap
在没有包装器的情况下将它传递给您,也许一次一件。我只想知道如何称呼x
所指的相关的内部单子内容,至少部分是这样,这样我就可以停止使用所有这些笨拙的语言。
对于这个事物/数据/价值/东西/whatever-it-is,是否有一个标准或约定俗成的术语?
如果不是,那“糖果”呢?
【问题讨论】:
我一直听说它是 Monad 的“价值”,尽管我承认在谈论List
s 和 Set
s 时这不太有意义。
同样以一种完全非标准的方式,我有时使用“基础值”,而不是“一元值”(和/或“函数值”)。实际上,“计算值”听起来不错。
如果我必须给它起个名字,我可能会称它为 monadic state(或 monad's state),例如Maybe
可以处于Just
(并包含一个值)或Nothing
状态,并且该状态是一元计算的结果。这解决了一点价值/数据的麻烦。但是,由于还有 State
monad,这可能有点令人困惑。备注:由于没有一个标准术语,我相信几乎所有的答案都会产生主要意见。
我会建议 monand 作为操作数,但这只是一个蓝天想法。否则,对于所有此类 -and 或 -andy 概念,我会坚持使用糖果。
让我缩小您的问题范围。如果在M[T]
M
被称为“monad”,那你怎么指T
?
【参考方案1】:
试图说“x
被绑定”会让你失败。让我解释一下,并引导您在谈论这些事情时以更好的方式表达自己。
假设我们有:
someList.flatMap(x => some_expression)
如果我们知道 someList 的类型为 List[Int]
,那么我们可以有把握地说 在 some_expression 内部,x
绑定到一个类型为 Int
的值。注意警告,“在 some_expression 中”。这是因为,给定someList = List(1,2,3)
,x
将依次采用它们中的每一个的值:1
、2
和 3
。
考虑一个更通用的例子:
someMonadicValue.flatMap(x => some_expression)
如果我们对someMonadicValue
一无所知,那么我们就不会知道如何调用some_expression
。它可能运行一次或三次(如上面的示例),或者延迟运行,或者异步运行,或者它可能在 someMonadicValue 完成后被调度(例如期货),或者它可能永远不会被使用(例如空列表,无)。 Monad 接口不包括关于何时或如何使用someExpression
的推理。所以你能说的关于x
的内容仅限于some_expression
的上下文,无论何时 并且然而 some_expression
恰好被评估。
回到这个例子。
someMonadicValue.flatMap(x => some_expression)
您想说“x
是 someMonadicValue
的 ???”。而您正在寻找准确替换 ??? 的词。好吧,我在这里告诉你,你做错了。如果你想谈论x
,那就去做吧
-
在
some_expression
的上下文中。在这种情况下,请使用我上面给你的粗体短语:“在 some_expression 内部,x
绑定到 Foo
类型的值。”或者,您也可以谈论x
...
对您正在处理的 monad 有更多的了解。
在情况 #2 中,例如,对于 someList.flatMap(x => some_expression)
,您可以说“x
是 someList
的每个元素。”对于someFuture.flatMap(x => some_expression)
,您可以说“x
是someFuture
的成功未来值,如果它确实完成并成功的话。”
你看,这就是 Monad 的美妙之处。 那个???你试图描述的,是 Monad 接口抽象出来的东西。现在你明白为什么给予如此困难了吗???一个名字?这是因为它对每个特定的 monad 有不同的名称和不同的含义。 这就是 Monad 抽象的意义所在:在同一个计算接口下统一这些不同的概念。
【讨论】:
【参考方案2】:免责声明:我绝对不是函数式编程术语方面的专家,我希望以下内容不会从您的角度回答您的问题。对我来说,问题在于:如果选择一个术语需要专业知识,那么理解也是如此。
选择合适的术语很大程度上取决于:
您期望的语言正确程度,以及 您的受众,以及某些术语的相应含义。关于语言正确性,问题是您是否要正确引用绑定到x
的值/数据,或者您是否可以接受某种(不正确的)抽象。就受众而言,我主要区分具有扎实函数式编程背景的受众和来自其他编程范式的受众。在前者的情况下,选择术语可能并不完全重要,因为概念本身是熟悉的,并且许多术语会导致正确的关联。 cmets中的讨论已经包含了一些针对这个案例的非常好的建议。但是,讨论还表明,您需要一定的函数式编程背景才能了解某些术语背后的基本原理。
对于没有函数式编程背景的观众,我宁愿牺牲语言的正确性来换取可理解性。在这种情况下,我经常将其称为“基础类型”,只是为了避免通过尝试引用“monad 中的事物”本身可能会造成的任何混淆。显然,说“x
绑定到底层类型”是错误的。然而,对我来说更重要的是我的听众完全理解一个概念。由于大多数程序员都熟悉容器及其底层类型,因此我的目标是(有缺陷的)关联“底层类型”=>“容器中的事物”=>“容器中的事物” monad”,这似乎经常起作用。
TL;DR:在正确性和可访问性之间总是存在权衡。在函数式编程方面,有时将偏见转向后者会有所帮助。
【讨论】:
【参考方案3】:flatMap
不会多次调用 Kleisli 箭头。而且“那个东西”不在单子“内部”。
flatMap
将 Kleisli 箭头举向 monad。您可以将其视为构造,类型之间的箭头M[A] => M[B]
(A
,B
)提升到单子(M[A]
,M[B]
),给定一个 Kleisli 箭头@ 987654328@.
所以x => f(x)
中的x
是被提升的值。
【讨论】:
【参考方案4】:什么数据?
data Monady a = Monady
monad 的值是 monad 的值,它们的包装类型可能完全是虚构的。也就是说,当它存在的时候谈论它可能会让你感到痛苦。
您要谈论的是像Monad m => a -> m b
这样的延续,因为它们保证存在。有趣的事情发生在(>>=)
使用这些延续。
【讨论】:
【参考方案5】:'Item' 看起来不错? '项目参数'如果您需要更具体。
源数据可以包含多个项目,或者操作可以多次调用它。 Element 对于第一种情况往往更具体,Value 对于来源来说是单一的,对于列表使用不明智,但 Item 涵盖所有情况都正确。
免责声明:我对通俗英语的了解比对 FP 的了解更多。
【讨论】:
【参考方案6】:退后一步。
monad 不仅仅是包装了值 a
的函子 m
。 monad 是 endofunctors 的堆栈(即m
的组合)以及join
运算符。这就是著名的俏皮话——单子是内函子类别中的幺半群,有什么问题? -- 来自。
(整个故事是这个俏皮话意味着m
的组成是另一个m
,由join
见证)
(m a)
类型的事物通常称为单子动作。您可以调用a
操作的结果。
【讨论】:
以上是关于你把包裹在单子里的数据叫做啥?的主要内容,如果未能解决你的问题,请参考以下文章