Functor 和 Monad 有什么区别?
What is the difference between a Functor and a Monad?
这里有类似的问题,但它们与特定的编程语言有关,我正在寻找概念层面的答案。
据我所知,函子本质上是不可变的容器,它公开 map() API 派生另一个函子。哪个加法使得将特定函子称为 monad 成为可能?
据我了解,每个 monad 都是一个 functor,但并非每个 functor 都是一个 monad。
(请注意,这将是对范畴论概念的简化解释)
函子
Functor 是从一组值 a 到另一组值的函数:a -> b
。对于编程语言,这可能是来自 String -> Integer
的函数:
function fn(text: string) : integer
作文
组合是指将一个函数的值用作下一个函数值的输入:fa(fb(x))
。例如:
hash(lowercase(text))
单子
Monad 允许组合不可组合的 Functors,通过在组合中添加额外功能来组合 Functors,或两者兼而有之。
第一个例子是 Functor 的 Monad String -> (String, Integer)
第二个例子是一个 Monad,它计算在一个值上调用的函数的数量
一个 Monad 包含一个 Functor T
,它负责您想要的功能以及另外两个功能:
input -> T(input)
T(T(input)) -> T(input)
第一个函数允许将您的输入值转换为我们的 Monad 可以组合的一组值。第二个函数允许合成。
所以总而言之,每个 Monad 都不是 Functor,而是使用 Functor 来完成它的目的。
让我在不涉及范畴论的情况下解释一下我的理解:
Functors 和 monad 都提供了一些工具 来包装输入,返回包装输出。
Functor = unit + map(即工具)
其中,
unit
= 接受原始输入并将其包装在一个小上下文中的东西。
map
= 将函数作为输入的工具,将其应用于包装器中的原始值,然后 returns 包装结果。
示例:让我们定义一个将整数加倍的函数
// doubleMe :: Int a -> Int b
const doubleMe = a => 2 * a;
Maybe(2).map(doubleMe) // Maybe(4)
Monad = unit + flatMap (or bind or chain)
flatMap
= 压平 map
的工具,顾名思义。通过下面的示例很快就会清楚。
示例:假设我们有一个柯里化函数,它仅在两个字符串都不为空时才附加两个字符串。
让我定义一个如下:
append :: (string a,string b) -> Maybe(string c)
现在让我们看看map
(Functor
自带的工具)的问题,
Maybe("a").map(append("b")) // Maybe(Maybe("ab"))
这里怎么有两个Maybe
?
嗯,这就是 map
所做的;它将提供的函数应用于包装值并包装结果。
让我们把它分成几个步骤,
将映射函数应用于包装值
;这里的映射函数是 append("b")
,包装值是 "a"
,结果是 Maybe("ab")
.
包装结果,returns Maybe(Maybe("ab"))
.
现在我们感兴趣的值被包裹了两次。 flatMap
来拯救了。
Maybe("a").flatMap(append("b")) // Maybe("ab")
当然,functor 和 monad 也必须遵循一些其他的规律,但我相信这不在要求的范围内。
Swift Functor, Applicative, Monad
仿函数、应用函数、单子:
- 解决同样的问题 - 将包装值处理到上下文中(class)
- 使用闭包[About]
- return 上下文的新实例(class)
区别在于闭包的参数
伪代码:
class SomeClass<T> {
var wrappedValue: T //wrappedValue: - wrapped value
func foo<U>(function: ???) -> Functor<U> { //function: - function/closure
//logic
}
}
在哪里???
function: (T) -> U == Functor
function: SomeClass< (T) -> U > == Applicative
function: (T) -> SomeClass<U> == Monad
函子
Functor 将 function
应用于 wrapped value
伪代码:
class Functor<T> {
var value: T
func map<U>(function: (T) -> U) -> Functor<U> {
return Functor(value: function(value)) //<- apply a function to value
}
}
Applicative or applicative functor
Applicative 将 wrapped function
应用于 wrapped value
。
与 Functor 的区别是 wrapped function
而不是 function
伪代码:
class Applicative<T> {
var value: T
func apply<U>(function: Applicative< (T) -> U >) -> Applicative<U> {
return Applicative(value: unwrappedFunction(value))
}
}
Monad
Monad 将 function
(其中 return 是 wrapped value
)应用于 wrapped value
伪代码:
class Monad<T> {
var value: T
func flatMap<U>(function: (T) -> Monad<U>) -> Monad<U> { //function which returns a wrapped value
return function(value) //applies the function to a wrapped value
}
}
Swift:
Optional
,Collection
,Result
是Functor和Monad
String
是 Functor
作为示例可选
enum CustomOptional<T> {
case none
case some(T)
public init(_ some: T) {
self = .some(some)
}
//CustomOptional is Functor
func map<U>(_ transform: (T) -> U) -> CustomOptional<U> {
switch self {
case .some(let value):
let transformResult: U = transform(value)
let result: CustomOptional<U> = CustomOptional<U>(transformResult)
return result
case .none:
return .none
}
}
//CustomOptional is Applicative
func apply<U>(transformOptional: CustomOptional<(T) -> U>) -> CustomOptional<U> {
switch transformOptional {
case .some(let transform):
return self.map(transform)
case .none:
return .none
}
}
//CustomOptional is Monad
func flatMap<U>(_ transform: (T) -> CustomOptional<U>) -> CustomOptional<U> {
switch self {
case .some(let value):
let transformResult: CustomOptional<U> = transform(value)
let result: CustomOptional<U> = transformResult
return result
case .none:
return .none
}
}
}
这里有类似的问题,但它们与特定的编程语言有关,我正在寻找概念层面的答案。
据我所知,函子本质上是不可变的容器,它公开 map() API 派生另一个函子。哪个加法使得将特定函子称为 monad 成为可能?
据我了解,每个 monad 都是一个 functor,但并非每个 functor 都是一个 monad。
(请注意,这将是对范畴论概念的简化解释)
函子
Functor 是从一组值 a 到另一组值的函数:a -> b
。对于编程语言,这可能是来自 String -> Integer
的函数:
function fn(text: string) : integer
作文
组合是指将一个函数的值用作下一个函数值的输入:fa(fb(x))
。例如:
hash(lowercase(text))
单子
Monad 允许组合不可组合的 Functors,通过在组合中添加额外功能来组合 Functors,或两者兼而有之。
第一个例子是 Functor 的 Monad
String -> (String, Integer)
第二个例子是一个 Monad,它计算在一个值上调用的函数的数量
一个 Monad 包含一个 Functor T
,它负责您想要的功能以及另外两个功能:
input -> T(input)
T(T(input)) -> T(input)
第一个函数允许将您的输入值转换为我们的 Monad 可以组合的一组值。第二个函数允许合成。
所以总而言之,每个 Monad 都不是 Functor,而是使用 Functor 来完成它的目的。
让我在不涉及范畴论的情况下解释一下我的理解:
Functors 和 monad 都提供了一些工具 来包装输入,返回包装输出。
Functor = unit + map(即工具)
其中,
unit
= 接受原始输入并将其包装在一个小上下文中的东西。
map
= 将函数作为输入的工具,将其应用于包装器中的原始值,然后 returns 包装结果。
示例:让我们定义一个将整数加倍的函数
// doubleMe :: Int a -> Int b
const doubleMe = a => 2 * a;
Maybe(2).map(doubleMe) // Maybe(4)
Monad = unit + flatMap (or bind or chain)
flatMap
= 压平 map
的工具,顾名思义。通过下面的示例很快就会清楚。
示例:假设我们有一个柯里化函数,它仅在两个字符串都不为空时才附加两个字符串。
让我定义一个如下:
append :: (string a,string b) -> Maybe(string c)
现在让我们看看map
(Functor
自带的工具)的问题,
Maybe("a").map(append("b")) // Maybe(Maybe("ab"))
这里怎么有两个Maybe
?
嗯,这就是 map
所做的;它将提供的函数应用于包装值并包装结果。
让我们把它分成几个步骤,
将映射函数应用于包装值 ;这里的映射函数是
append("b")
,包装值是"a"
,结果是Maybe("ab")
.包装结果,returns
Maybe(Maybe("ab"))
.
现在我们感兴趣的值被包裹了两次。 flatMap
来拯救了。
Maybe("a").flatMap(append("b")) // Maybe("ab")
当然,functor 和 monad 也必须遵循一些其他的规律,但我相信这不在要求的范围内。
Swift Functor, Applicative, Monad
仿函数、应用函数、单子:
- 解决同样的问题 - 将包装值处理到上下文中(class)
- 使用闭包[About]
- return 上下文的新实例(class)
区别在于闭包的参数
伪代码:
class SomeClass<T> {
var wrappedValue: T //wrappedValue: - wrapped value
func foo<U>(function: ???) -> Functor<U> { //function: - function/closure
//logic
}
}
在哪里???
function: (T) -> U == Functor
function: SomeClass< (T) -> U > == Applicative
function: (T) -> SomeClass<U> == Monad
函子
Functor 将 function
应用于 wrapped value
伪代码:
class Functor<T> {
var value: T
func map<U>(function: (T) -> U) -> Functor<U> {
return Functor(value: function(value)) //<- apply a function to value
}
}
Applicative or applicative functor
Applicative 将 wrapped function
应用于 wrapped value
。
与 Functor 的区别是 wrapped function
而不是 function
伪代码:
class Applicative<T> {
var value: T
func apply<U>(function: Applicative< (T) -> U >) -> Applicative<U> {
return Applicative(value: unwrappedFunction(value))
}
}
Monad
Monad 将 function
(其中 return 是 wrapped value
)应用于 wrapped value
伪代码:
class Monad<T> {
var value: T
func flatMap<U>(function: (T) -> Monad<U>) -> Monad<U> { //function which returns a wrapped value
return function(value) //applies the function to a wrapped value
}
}
Swift:
Optional
,Collection
,Result
是Functor和MonadString
是 Functor
作为示例可选
enum CustomOptional<T> {
case none
case some(T)
public init(_ some: T) {
self = .some(some)
}
//CustomOptional is Functor
func map<U>(_ transform: (T) -> U) -> CustomOptional<U> {
switch self {
case .some(let value):
let transformResult: U = transform(value)
let result: CustomOptional<U> = CustomOptional<U>(transformResult)
return result
case .none:
return .none
}
}
//CustomOptional is Applicative
func apply<U>(transformOptional: CustomOptional<(T) -> U>) -> CustomOptional<U> {
switch transformOptional {
case .some(let transform):
return self.map(transform)
case .none:
return .none
}
}
//CustomOptional is Monad
func flatMap<U>(_ transform: (T) -> CustomOptional<U>) -> CustomOptional<U> {
switch self {
case .some(let value):
let transformResult: CustomOptional<U> = transform(value)
let result: CustomOptional<U> = transformResult
return result
case .none:
return .none
}
}
}