【问题标题】:Why flatmap is needed in state monads?为什么在状态单子中需要平面图?
【发布时间】:2019-09-17 12:42:58
【问题描述】:

对不起,这个非常幼稚的问题。

我知道状态单子的本质是一个类型 S => (S,A) 的映射,其中 S 是状态的类型,A 是计算结果的类型。那么状态单子的本质将被定义为(在 Scala 中)

class StateMonad[S,A](transition: S => (S,A))

这应该是全部,没什么大不了的。为什么这么多书还将flatMap 放入状态单子的定义中?除了诸如“否则,与状态一起玩会变得容易出错”之类的论点之外,还有什么动机?据我所知,flatMap 主要适用于列表或集合。所以,我真的很想念这里的一些大图。有人可以澄清吗?谢谢你。

我希望看到不需要单子知识的答案。事实上,在真正引入 monad 概念之前,我正在阅读教科书中的 State Monad 章节。我开始学习使用的语言是 Scala。

【问题讨论】:

  • flatMap 是所有 monad 的要求。
  • @lee 是的,这是我理解的问题,因为我在实际引入 monad 概念之前正在阅读 State Monad 章节。你能解释一下为什么需要 flatMap 来处理状态或特定的状态单子吗?
  • 是的,flatMap 不是必需的吗?有些地方称它为bind,但最终它需要一个函数,该函数返回一个 monad 并用它转换当前的 monad。所以它不仅是 State monad,而且任何 monad 都需要它。没有它,您将无法有效地使用 monad。

标签: functional-programming state-monad


【解决方案1】:

flatMap 函数是使用 Monad 而不是像 FunctorApplicative 这样较弱(因此更通用)的结构所获得的额外功能的原因。对于State,此函数的类型为:

def flatMap[S, A, B](f: A => State[S, B], state: State[S, A]): State[S, B]

在函数f 中,您可以检查先前有状态计算的结果并使用它来决定如何在其余计算中进行,例如

def branch1: State[Int, String]
def branch2: State[Int, String]
def decide(s: State[Int, Int]): State[Int, String] =
    flatMap(x => if x > 5 then branch1 else branch2, s)

【讨论】:

  • @zell - 哪一点不清楚? flatMap 允许您将 State 值组合在一起,同时根据先前计算的结果在备选方案之间进行选择。
  • 我发现弱属性和一般属性之间的相关性非常有趣。弱到底是什么意思?当您知道的部分(即它实现的类型类)不太具体时,一个结构是否比另一个结构更弱?不过,这种解释仍然很模糊。是什么让 typeclass 比另一个 typeclass 不那么具体?
  • @bob - 是的,我的意思是类型类不那么具体,因此也不那么强大。 ApplicativeFunctor 的子类型,MonadApplicative 的子类型,这些类定义的操作赋予您更多的表现力。
猜你喜欢
  • 2017-08-02
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 2015-12-26
  • 2020-05-10
  • 2020-02-04
相关资源
最近更新 更多