.net - 状态单子(monad),为什么不是一个元组?

标签 .net f# functional-programming monads

我刚刚把我的头绕在单子(monad)上(至少我想我想我有),更具体地说是状态单子(monad),有些人比我聪明得多,所以我可能对这个问题有所了解.

无论如何,状态单子(monad)通常用 M<'a> 来实现,如下所示(F#):

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

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

编辑:为清楚起见添加了示例
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 一起工作。 ,它表示采用一些初始状态并产生结果(连同状态的新值)的计算。

如果您问我们是否给这种类型一些特殊的名称(例如 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 的函数。值(value)观。我认为第一个的主要好处是您可以更容易地意识到可以从其他单子(monad)计算中使用该类型(使用 state { ... } 编写)。

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

关于.net - 状态单子(monad),为什么不是一个元组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2595673/

相关文章:

.net - 使用 Win32 API 写入应用程序事件信息

c# - 与 Parameters.Add 和 Parameters.AddWithValue 的区别

c# - 从 F# 调用 C# 异步方法会导致死锁

data-structures - F# 用于高频实时流数据的不可变数据结构

kotlin - 减少/折叠中的两个累加器

c# - 确定数组与目标数组的接近程度

.net - 如何覆盖 WinForms 中数据绑定(bind)控件上的错误消息?

f# - 如何在FsCheck中轻松过滤出有区别的工会案例?

python - 你什么时候会使用 reduce() 而不是 sum()?

oop - 柯里化(Currying)和重载一样吗?