这里也有类似的问题,但它们与特定的编程语言相关联,我正在寻找概念层面的答案。
据我所知,Functors本质上是不可变容器,它们公开了 map() API,它衍生出另一个仿函数。哪个添加可以将特定的仿函数称为monad?
据我所知,每个monad都是一个仿函数,但不是每个仿函数都是monad。
答案 0 :(得分:4)
(请注意,这将是类别理论概念的简化说明)
Functor是一组值a到另一组值的函数:a -> b
。对于编程语言,这可以是来自String -> Integer
:
function fn(text: string) : integer
组合是指您使用一个函数的值作为下一个值fa(fb(x))
的值的输入。例如:
hash(lowercase(text))
Monad允许编写其他不可组合的Functors,通过在合成中添加额外的功能来组合Functors,或者两者兼而有之。
第一个例子是玩家的Monad String -> (String, Integer)
第二个例子是Monad,它计算值上调用的函数数量
Monad包含一个Functor T
,它负责您想要的功能以及另外两个功能:
input -> T(input)
T(T(input)) -> T(input)
第一个函数允许将输入值转换为Monad可以组合的一组值。第二个功能允许合成。
总而言之,每个Monad都不是Functor,而是使用Functor来完成它的目的。
答案 1 :(得分:0)
让我不用进入类别理论就能解释我的理解
Functor和monad都提供一些工具来包装输入并返回包装输出。
Functor =单位+地图(工具)
在哪里, unit =它需要原始输入并将其包装在较小的上下文中。
map =它是一种将函数作为输入,将其应用于包装器中的原始值并返回包装结果的工具。
示例:让我们定义一个将整数加倍的函数 // doubleMe :: Int a-> Int b const doubleMe = a => 2 * a; Maybe(2).map(doubleMe)// Maybe(4)
Monad = unit + flatMap(或绑定或链接)
flatMap =当名称溢出时,它是使地图变平的工具。下面的示例很快就会清楚。
示例:假设我们有一个curried函数,仅当两个字符串都不为空时才追加两个字符串。
让我定义一个如下,
append ::(字符串a,字符串b)->也许是(字符串c)
现在让我们看看map(Functor附带的工具)的问题,
Maybe(“ a”)。map(append(“ b”))// Maybe(Maybe(“ ab”))
两个人怎么可能在这里?
好吧,这就是map的作用,它将提供的函数应用于包装的值并包装结果。
让我们分步进行吧
步骤1:将映射函数应用于包装后的值 此处映射的函数为append(“ b”),包装的值为“ a”,结果为Maybe(“ ab”)
步骤2:包装返回Maybe(Maybe(“ ab”))的结果。
现在我们感兴趣的值被包装两次。这里是flatMap来进行救援。 Maybe(“ a”)。flatMap(append(“ b”))// Maybe(“ ab”)
当然,函子和monad也必须遵守其他一些法律,但我认为这不在要求的范围之内。