【发布时间】:2019-05-29 21:24:49
【问题描述】:
Scala 的Option 既是单子又是函子?
据我了解,functor 只是一种公开以下 API 的数据类型:
函子:
wrap(或
apply)接受一个原语并将其包装在函子内map接受函子,解包,应用某些函数并重新包装
所以Option 是一个函子。因为我可以将Option 应用于给我Option[T] 的原语。我也可以在Option 上map 获取函子内部的内容并在Option 中重新打包。
monad 有何不同?我原以为 monad 也有 apply 函数和 map 函数。从this article 我推测一个单子也有flatMap?哪个被简单地定义为 map 但没有在 monad 中重新打包结果? (或者是 map 没有将结果重新打包到函子中?!)
既然Option 同时提供map 和flatMap,这是否意味着Option 既是函子又是monad?
【问题讨论】:
-
每个 Monad 也是一个 Functor。不仅是
Option,还有任何Monad。 - 其次,apply不是来自 Functor,而是来自 Applicative (这也意味着每个 Applicative 也是一个 Functor,每个Monad也是一个Aplicative)。 - 第三,是的,一个 Monad 被定义为还有一个flatMap,它最好被认为是一个知道内部上下文的map,或者是一个map,后跟一个flatten。但是,恕我直言,区分它们的最佳方法是类型,map[A, B](fa: F[A])(f: A => B): F[B]VSflatMap[A, B](fa: F[A])(f: A => F[B]): F[B]。 -
您可能会发现 infographic (by tpolecat) 对了解分类类型类之间的关系很有用。
-
Option本身不是函子或单子。函子是一个三元组(满足函子定律);某些类型 (F)、单位函数 ((A) => F[A]) 和映射函数 ((F[A], A => B) => F[B])。 monad 是一个三元组(满足 monad 法则);某种类型 (M)、单位函数 ((A) => M[A]) 和 flatMap(或绑定)函数 ((M[A], A => M[B]) => M[B])。 -
@franklin 不是真的,让我用上下文扩展我的意思。大多数“monads” (引号是为了讨论它们实际上不是monads),例如
Option、Either、List、IO被称为 Contexts 或 Effects,这是因为它们封装了 pure 值,这些值具有额外的 side-effect 关联与它们(此过程称为reification),例如Option封装了非总计算的效果,或者换句话说,一个可能或可能的值不存在。希望这可以清楚上下文是什么,让我们回顾一下我为什么要使用 “aware”。 -
@franklin 是的,我只需将 “我可能会收到一个也包含在上下文中的输入” 更改为 我会 (它是不是可选的) 接收也包装在上下文中的输入 - “所以我将解开输入执行一些功能并将输出包装在上下文中”是的,您会将结果包装在上下文中,但函数的结果也包装在上下文中,因此,您也需要将其解包。但是,是的,
map和flatMap都会传播上下文。恕我直言,理解它们的一个很好的练习是从头开始为Option、List和IO等各种类型实现它们。