【问题标题】:What are the advantages of a wrapped up the state monad?包裹状态单子的优点是什么?
【发布时间】:2013-11-24 22:31:40
【问题描述】:

这可能是一个愚蠢的,但看看(Eliminating my explicit state passing via like, monads and stuff

type State<'s,'a> = State of ('s -> 'a * 's)

type StateBuilder<'s>() =
  member x.Return v : State<'s,_> = State(fun s -> v,s)
  member x.Bind(State v, f) : State<'s,_> =
    State(fun s ->
      let (a,s) = v s
      let (State v') = f a
      v' s)

let withState<'s> = StateBuilder<'s>()

let getState = State(fun s -> s,s)
let putState v = State(fun _ -> (),v)

let runState (State f) init = f init

's -&gt; 'a * 's 包裹在State 中有什么好处。这只是一种安全预防措施吗?

【问题讨论】:

  • @Gary.S 这个问题是问为什么状态单子是用函数而不是元组来实现的,而不是为什么状态函数有时被包装在另一种类型中。

标签: f# state-monad


【解决方案1】:

我认为这更多的是偏好或便利性问题,而不是安全性问题;有些人喜欢像这样将函数包装在一个区分大小写的联合类型中,而有些人则不喜欢。

我不喜欢包装函数,因为它会引入少量额外开销,并且会阻止编译器进行一些优化。在我的ExtCore 库中,我实现了同样的事情,使用类型别名而不是创建实际类型来包装函数:

type StateFunc<'State, 'T> = 'State -> 'T * 'State

【讨论】:

    【解决方案2】:

    我的猜测是包装器来自 Haskell 传统和可以泛化于 monad 的语言。 在这些语言中,您可以拥有一个通用的 &gt;&gt;= 函数,但每种类型只能有一个实现,有时会有不止一个有用的实现。

    'a * 'b'a-&gt;'b 等非常通用的类型就是这种情况。

    对于函数'a -&gt; 'b,您可以定义一个读取器、一个状态或一个解析器单子,判断哪个实现拾取的方法是将它们包装起来,因此它们具有不同的类型。

    在 F# 中情况不同,大多数 monad 库没有定义通用的 &gt;&gt;= 实现,因为在 .NET 中没有干净的方法来执行此操作,因此无需包装 State,因为您将明确应用&gt;&gt;= 和其他 monad 相关函数的具体实现。

    在没有泛型函数或重载的情况下,如果你愿意,你仍然可以包装你的 State monad,但是你必须像在 Haskell 中一样包装和解包代码,在这种情况下,决定取决于你想要定制多少你的类型,那是general question,不仅仅是单子。

    【讨论】:

      猜你喜欢
      • 2015-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      相关资源
      最近更新 更多