状态 Monad,为什么不是元组呢?

2023-11-22

我刚刚把我的头围绕在单子上(至少我想认为我有),更具体地说是状态单子,一些比我聪明得多的人发现了这一点,所以我可能会回答这个问题。

无论如何,状态 monad 通常使用 M 来实现,如下所示 (F#):

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

现在我的问题:有什么理由不能在这里使用元组吗?除此之外,之间可能存在歧义MonadA<'a, 'b> and MonadB<'a, 'b>这都将成为等价的('a * 'b) tuple.

编辑:为了清楚起见添加了示例

type StateMonad() =
  member m.Return a = (fun s -> a, s)
  member m.Bind(x, f) = (fun s -> let a, s_ = x s in f a s_)

let state = new StateMonad()
let getState = (fun s -> s, s)
let setState s = (fun _ -> (), s) 
let execute m s = m s |> fst

The 状态单子本质上适用于一种类型'state -> 'res * 'state,它表示需要一些时间的计算初始状态并产生结果(以及状态的新值)。

如果您问我们是否为这种类型指定一些特殊名称(例如State<'state, 'res>)那么答案是这并不重要。为类型赋予一些特殊名称的唯一目的是使代码更具可读性。例如,让我们看看以下示例的两种可能的类型签名:

let foo n = state {
  let! m = getState()
  do! setState(m + 1)
  return sprintf "Result: %d" (n * m) }

// Using State<'state, 'res> type:
val foo : int -> State<int, string>

// Using the underlying representation:
val foo : int -> int -> int * state

第一种类型签名更清楚地表明我们正在某个 monad 中编写函数。第二个例子只是一个需要两个参数的函数int价值观。我认为第一个的主要好处是您可以更容易地意识到该类型可以从其他一元计算中使用(使用state { ... }).

然而,正如我已经指出的,这不是技术要求。人们可能会使用这种风格,因为许多 monad 来自 Haskell,其中 monad 与type(例如State<'state, 'res>)而不是一个计算生成器(例如state),所以为 Haskell 中的每个 monad 定义一个新类型听起来是个好主意。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

状态 Monad,为什么不是元组呢? 的相关文章

随机推荐