在最近简要回顾了Haskell之后,对于monad本质上是什么,有什么简单、简洁、实用的解释?
我发现,我遇到的大多数解释都很难理解,而且缺乏实际细节。
在最近简要回顾了Haskell之后,对于monad本质上是什么,有什么简单、简洁、实用的解释?
我发现,我遇到的大多数解释都很难理解,而且缺乏实际细节。
当前回答
解释
当用C#/Java术语解释时,这很简单:
monad是一个接受参数并返回特殊类型的函数。这个monad返回的特殊类型也称为monad。(monad是#1和#2的组合)有一些语法糖可以使调用此函数和类型转换更容易。
实例
monad有助于使函数式程序员的生活更轻松。典型示例:Maye monad接受两个参数,一个值和一个函数。如果传递的值为null,则返回null。否则它将计算函数。如果我们需要一个特殊的返回类型,我们也可以调用这个返回类型Maybe。一个非常粗糙的实现如下所示:
object Maybe(object value, Func<object,object> function)
{
if(value==null)
return null;
return function(value);
}
这在C#中是非常无用的,因为这种语言缺乏使monad有用所需的语法糖。但是monad允许您用函数式编程语言编写更简洁的代码。
通常程序员在链中调用monad,如下所示:
var x = Maybe(x, x2 => Maybe(y, y2 => Add(x2, y2)));
在本例中,只有当x和y都为非null时,才会调用Add方法,否则将返回null。
答复
回答最初的问题:monad是一个函数和一个类型。就像一个特殊接口的实现。
其他回答
数学思维
简而言之:用于组合计算的代数结构。
返回数据:创建一个只需在monad世界中生成数据的计算。
(return data)>>=(return func):第二个参数接受第一个参数作为数据生成器,并创建连接它们的新计算。
您可以认为(>>=)和return本身不会进行任何计算。他们只是简单地组合和创建计算。
当且仅当main触发时,任何monad计算都将被计算。
(另请参见“什么是monad?”中的答案)
蒙纳斯的一个很好的动机是西格菲(丹·皮波尼)的《你本可以发明蒙纳斯!(也许你已经有了)。还有很多其他monad教程,其中许多都试图使用各种类比以“简单的术语”来解释monad:这就是monad教程谬论;避开它们。
正如MacIver博士在《告诉我们为什么你的语言很糟糕》中所说:所以,我讨厌Haskell的事情:让我们从显而易见的开始。Monad教程。不,不是单子。特别是教程。他们没完没了,夸夸其谈,亲爱的上帝,他们太乏味了。此外,我从未见过任何令人信服的证据表明它们确实有帮助。阅读类定义,编写一些代码,忘掉这个可怕的名字。
你说你懂“也许莫纳德”吗?很好,你在路上了。只要开始使用其他monad,迟早你会了解monad的一般含义。
(如果你以数学为导向,你可能想忽略几十个教程,学习定义,或遵循类别理论的讲座:)定义的主要部分是Monad M包含一个“类型构造器”,为每个现有类型“T”定义一个新类型“M T”,以及在“常规”类型和“M”类型之间来回移动的一些方式。]
同样,令人惊讶的是,对monad最好的介绍之一实际上是介绍monad的早期学术论文之一,Philip Wadler的Monad for functional programming。它实际上有一些实用的、非平凡的激励性例子,与许多人工教程不同。
对于来自命令式背景(c#)的人,
考虑以下代码
bool ReturnTrueorFalse(SomeObject input)
{
if(input.Property1 is invalid)
{
return false;
}
if(input.Property2 is invalid)
{
return false;
}
DoSomething();
return true;
}
您会看到很多这样的代码,甚至不会看到早期返回,但所有检查都是嵌套完成的。现在,Monad是一种模式,它可以像下面一样被压平
Monad<bool> ReturnTrueorFalse(SomeObject input) =>
from isProperty1Valid in input.Property1
from isProperty2Valid in input.Property2
select Monad.Create(isProperty1Valid && isProperty2Valid);
这里有几点需要注意。首先,更改函数的返回值。其次,输入的两个财产都必须是Monad。接下来,Monad应该实现SelectMany(LINQ的展平运算符)。由于SelectMany是为该类型实现的,因此可以使用查询语法编写语句
那幺,什么是莫纳德?它是一种以可组合方式对返回相同类型的表达式进行扁平化的结构。这在函数式编程中特别有用,因为大多数函数式应用程序倾向于将状态和IO保持在应用程序的边缘层(例如:控制器),并在整个调用堆栈中返回基于Monad的返回值,直到需要解包该值。当我第一次看到这张照片时,我最大的优点是它很容易在眼睛上看到,也很有陈腔滥调。
每个c#(现在几乎每个人)开发人员都能立即识别的Monad的最佳示例是async/await。在.Net4.5之前,我们必须使用ContinueWith编写基于任务的语句来处理回调,在async/await之后,我们开始使用同步语法来处理异步语法。这是可能的,因为Task是一个“monad”。
关于OOP开发人员的详细说明,请参阅本文,这是一个简单的实现和语言文本,其中包含许多很棒的Monad和大量关于函数式编程的信息
monad是用于封装状态变化的对象的东西。在不允许您具有可修改状态的语言(例如,Haskell)中最常遇到这种情况。
例如文件I/O。
您将能够使用文件I/O的monad来将不断变化的状态本质与使用monad的代码隔离开来。Monad内部的代码可以有效地忽略Monad外部世界的变化状态,这使您更容易理解程序的整体效果。
解释
当用C#/Java术语解释时,这很简单:
monad是一个接受参数并返回特殊类型的函数。这个monad返回的特殊类型也称为monad。(monad是#1和#2的组合)有一些语法糖可以使调用此函数和类型转换更容易。
实例
monad有助于使函数式程序员的生活更轻松。典型示例:Maye monad接受两个参数,一个值和一个函数。如果传递的值为null,则返回null。否则它将计算函数。如果我们需要一个特殊的返回类型,我们也可以调用这个返回类型Maybe。一个非常粗糙的实现如下所示:
object Maybe(object value, Func<object,object> function)
{
if(value==null)
return null;
return function(value);
}
这在C#中是非常无用的,因为这种语言缺乏使monad有用所需的语法糖。但是monad允许您用函数式编程语言编写更简洁的代码。
通常程序员在链中调用monad,如下所示:
var x = Maybe(x, x2 => Maybe(y, y2 => Add(x2, y2)));
在本例中,只有当x和y都为非null时,才会调用Add方法,否则将返回null。
答复
回答最初的问题:monad是一个函数和一个类型。就像一个特殊接口的实现。