状态 Monad,为什么不是元组? [英] State Monad, why not a tuple?

查看:33
本文介绍了状态 Monad,为什么不是元组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚了解了 monad(至少我想我有),更具体地说是 state monad,有些人比我更聪明,所以我可能是这样的带着这个问题.

I've just wrapped my head around monads (at least I'd like to think I have) and more specifically the state monad, which some people that are way smarter then me figured out, so I'm probably way of with this question.

无论如何,状态单子通常用 M<'a> 实现,就像这样(F#):

Anyway, the state monad is usually implemented with a M<'a> as something like this (F#):

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

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

Now my question: Is there any reason why you couldn't use a tuple here? Other then the possible ambiguity between MonadA<'a, 'b> and MonadB<'a, 'b> which would both become the equivalent ('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

推荐答案

State monad 本质上与 'state ->'res * 'state,它表示一个计算,它采用一些初始状态并产生结果(连同状态的新值).

The State monad essentially works with a type 'state -> 'res * 'state, which represents a computation that takes some initial state and produces result (together with a new value of the state).

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

If you're asking whether it makes any difference whether we give some special name to this type (e.g. State<'state, 'res>) then the answer is it doesn't really matter. The only purpose of giving some special name to the type is that it makes the code more readable. For example, let's look at the two possible type signatures of the following example:

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 { ... } 编写).

The first type signature more clearly says that we're writing function in some monad. The second example is just a function that takes two int values. I think the main benefit of the first one is that you can more easily realize that the type can be used from other monadic computation (written using state { ... }).

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

However, as I already noted, this isn't a technical requirement. People probably use this style, because many monads come from Haskell, where monads are associated with the type (such as State<'state, 'res>) and not a computation builder (such as state), so it sounds like a good idea to define a new type for every monad in Haskell.

这篇关于状态 Monad,为什么不是元组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆