当前位置: 首页 > 知识库问答 >
问题:

函子和单子有什么区别?

江向阳
2023-03-14

这里也有类似的问题,但它们与特定的编程语言有关,我正在寻找概念层面的答案。

据我所知,functor本质上是不可变的容器,它公开了派生另一个functor的map()API。哪种加法可以将特定的函子称为单子?

据我所知,每个仿函数都是仿函数,但不是每个仿函数都是单子。

共有3个答案

韩飞翮
2023-03-14

Swift函子,Applicative,Monad

函数,应用程序,单声道:

  • 解决同样的问题-在上下文中使用包装的值(类)
  • 使用闭包
  • 返回上下文(类)的新实例

不同之处在于闭包的参数

伪代码:

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将函数应用于包装值

伪代码:

class Functor<T> {
    var value: T
    func map<U>(function: (T) -> U) -> Functor<U> {
        return Functor(value: function(value)) //<- apply a function to value
    }
}

应用或应用仿函数

申请人将包装函数应用于包装值

带函子的diff是包装函数,而不是函数

伪代码:

class Applicative<T> {
    var value: T
    func apply<U>(function: Applicative< (T) -> U >) -> Applicative<U> {
        return Applicative(value: unwrappedFunction(value))
    }
}

单子

Monad将函数(返回包装值)应用于包装值

代码

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:

  • 可选集合结果是函子和单子

例如,可选

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
        }
    }
}

[Swift可选地图与平面地图]

施永宁
2023-03-14

(请注意,这将是对范畴理论概念的简化解释)

函子是从一组值A到另一组值的函数:A-

函数fn(文本:字符串):整数

合成是将一个函数的值用作下一个函数的值的输入:fa(fb(x))。例如:

哈希(小写(文本))

Monad允许组合不可组合的函数,通过在组合中添加额外的功能来组合函数,或者两者兼而有之。

>

  • 第一个例子是函子字符串的单子-

    第二个示例是一个Monad,它统计对一个值调用的函数数

    Monad包括一个FunctorT,它负责您想要的功能以及另外两个功能:

    • 输入-

    第一个函数允许将输入值转换为我们的Monad可以组成的一组值。第二个功能允许合成。

    总之,每个单子都不是一个函子,而是用一个函子来完成它的目的。

  • 茹元魁
    2023-03-14

    让我在不进入范畴理论的情况下解释我的理解:

    functor和monad都提供了一些工具来包装输入,返回包装输出。

    Functor=单元映射(即工具)

    哪里

    <代码>单位=接受原始输入并将其包装在一个小上下文中的东西。

    映射=将函数作为输入,将其应用于包装器中的原始值,并返回包装结果的工具。

    示例:让我们定义一个将整数加倍的函数

    // doubleMe :: Int a -> Int b
    const doubleMe = a => 2 * a;
    Maybe(2).map(doubleMe)  // Maybe(4)
    

    Monad=单位平面图(或绑定或链)

    flatMap=如其名称所示,用于展平贴图的工具。下面的例子很快就会清楚。

    示例:假设我们有一个curried函数,它只在两个字符串都不是空的情况下才附加两个字符串。

    让我定义如下:

    append :: (string a,string b) -> Maybe(string c)  
    

    现在让我们看看映射(Functor附带的工具)的问题,

    Maybe("a").map(append("b")) // Maybe(Maybe("ab"))  
    

    为什么这里有两个也许s?

    好吧,这就是map所做的;它将提供的函数应用于包装的值并包装结果。

    让我们把它分成几个步骤,

    >

    包装结果,返回Maybe(Maybe(“ab”))

    现在,我们感兴趣的值被包装了两次。下面是救援行动的平面图。

    Maybe("a").flatMap(append("b")) // Maybe("ab")
    

    当然,函子和单子也必须遵循其他一些定律,但我相信这不在所要求的范围之内。

     类似资料:
    • 我理解这两种方法的目标方法,其中最优子结构基于输入n计算最优解,而重叠子问题针对输入范围从1到n的所有解。 对于像棒切割问题这样的问题。在这种情况下,在寻找最佳切割时,我们是否考虑每个切割,因此可以将其视为重叠子问题,并自下而上进行工作。或者,我们考虑给定输入n的最优切割,并自上而下地工作。 因此,虽然它们最终处理的是最优性,但这两种方法之间的确切区别是什么。 我试着参考这个重叠的子问题,最优子结

    • 问题内容: 自从Postgres具备进行连接的能力以来,我一直在阅读它,因为我目前为团队执行复杂的数据转储,其中包含许多效率低下的子查询,这些查询使整个查询花费了四分钟或更长时间。 我知道联接可能会为我提供帮助,但是即使从Heap Analytics中阅读了类似这样的文章,我仍然不太了解。 联接的用例是什么?联接和子查询之间有什么区别? 问题答案: 什么 是 一个加入? 该功能是PostgreSQ

    • 问题内容: 我的工作应该使用并行技术,并且我是python的新用户。因此,我想知道您是否可以共享有关python和模块的一些资料。两者有什么区别? 问题答案: 该模块使您可以运行和控制其他程序。您可以使用计算机上的命令行启动的任何内容,都可以使用此模块运行和控制。使用它可以将外部程序集成到您的Python代码中。 该模块可让您将以python编写的任务划分为多个进程,以帮助提高性能。它提供与该模块

    • 本文向大家介绍` 单击 `和` 单击 `有什么区别?相关面试题,主要包含被问及` 单击 `和` 单击 `有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 绑定函数有三种方法 1、constructor绑定 2. 使用时绑定 3. 使用箭头函数 这种最简单 不用考虑this的指向问题 (但是会造成额外的渲染) 以上三种方法,第一种最优。 因为第一种构造函数只在组件初始化的时候执行一次, 第二种

    • 我在编写一个非常庞大的mib时遇到了问题,因为我只有一个代理与许多没有snmp的设备连接。所有设备都通过推送将相同类型的数据发送到代理,然后代理将snmp陷阱发送到snmp管理器。此外,Manager正在向代理发送SNMP GET。我想编写一个标准的mib,它适用于每个设备,管理器只需发送一些OID来获取对应的值,而不是数百个OID。一个非常庞大的mib意味着有很多分支。

    • 和 你什么时候会一个比另一个好?