Monads —示例和定义

例子

我们Swift程序员联系并使用了一些monad,甚至不知道它们是这样分类的:数组(以及所有其他Sequence)和Optionals都是此语句的有效示例。

还有一些框架可以实现其他monad:RxSwift,一种反应式编程框架,可以实现与这些主题相同的主题(可以同时观察和观察的对象)。

它们在纯函数式语言中甚至更有用,以便专门处理可控的副作用。 克里斯·史密斯(Chris Smith)在这篇文章中描述了其中的四个非常重要的部分,即“ Catapocalypse的四个骑士”:

  • 故障 -由于内存不足,无效的人工输入,网络中断等原因,功能可能导致错误;
  • 依赖 -从一个函数调用到下一个函数调用,作为有状态操作;
  • 不确定性 -来自相同参数的不同结果;
  • 破坏 -对世界有永久影响的行动,例如I / O。

我们可以用这些语言找到其他单子,以控制状态,记录(作家单子),IO和其他效果。

当考虑这些示例时,将单子作为容器/盒子的比喻变得更难以适应。 我认为它带来了一个隐式的结构概念,该结构很好地包含了Arrays和Optionals,但是需要扩展和重新研究才能容纳其他结构。

从我看来,看这些例子并从中开始似乎使学习者难以建立单子概念(甚至是目的)。 另一方面,理解其主要用法之一非常重要:定义一种以统一和可控的方式处理其他计算和副作用的通用方法。

目的

在跳到定义和概念之前,我认为重要的一点是,在函数式编程中使用monad的目的是允许将具有返回值类型的函数组成为另一个将不同类型作为参数的函数。 尽管如此,它并非旨在使每个返回值都与任何参数类型匹配:monads处理某个函数返回的某些泛型类型,以将它们与期望其关联类型作为参数的函数组成(例如:连接一个由返回的Array 一个需要整数的函数,例如f(Int )。

Monad具有多种用途,但它们的通用目的(至少从编程的角度而言)是连接事物。

定义

由于示例仅部分支持概念理解,因此让我们转到另一种方法:从定义的角度出发。

编程语言上的Monad是通用类型(例如:Array ),这意味着它与任何T类型(例如IntString等)或至少与具有某些约束的一组类型(例如Dictionary )相关联键值对:它们可以将任何类型都保存为值,但是键被限制为符合Hashable协议的类型。

除了是通用类型之外,monad还应该实现两个功能:

  • 单位函数 -用于monad类型M类型构造 函数 ,该类型构造 函数从关联的类型a接收值并将其转换为具有最小上下文M(a)的泛型类型-“处于最小上下文中”的含义取决于类型本身。 对于一个数组,接收到一个值,如整数1 ,它应该创建一个只有一个元素[1]的整数数组; (可选),接收字符串“ Hello!” 应该创建一个Optional ,其值为.some(“ Hello!”) 。 这可以扩展到任何其他monad类型。
  • 平面映射函数 -此函数是为具有关联类型a的monad M的每个实例实现的高阶函数(意味着:它接收另一个函数作为参数) 它接收作为参数的函数,该函数将类型a的值转换为相同类型M的另一个monad,但可以具有另一个关联类型b 。 平面地图函数应返回类型为M(b)的单子。 我们可以将此函数定义为M(a).flatMap(a→M(b))→M(b)flatMap(M(a)a→M(b))→M(b) (选择对您更清晰) 在某些编程语言(例如Haskell)中,平面映射函数也称为绑定函数

如前所述,该定义很简单(而不是复杂的定义),但是并没有带来更多了解单子的信息。

接下来,我将尝试使用更“正式”的monad定义:

Monad是endofunctors类别中的monoid ”。

什么?!!?!?! 😮😧😱

这个定义虽然很笨拙,但却是帮助我理解该概念的基础。 因此,我的下一篇文章将分解这个模糊的定义中存在的概念,并尝试说明如何在我们的代码中尽可能地使用它们。 从数学上讲,它们将不是精确的(因为我缺乏这样做的背景,也许对我们开发人员而言,它不会增加太多支持),但我希望它们至少使您更进一步地从编程的角度理解monad。 。

让我们从“ Monad是endofunctors类别中的monoids”的类别部分开始。

注意:如果要导航到特定帖子,则以下是所有与monad相关的帖子的列表。

    Interesting Posts