F# 在不使用可变性的情况下表示可变性是可能的吗?

F# 在不使用可变性的情况下表示可变性是可能的吗?,f#,functional-programming,immutability,monads,F#,Functional Programming,Immutability,Monads,在阅读了状态单子(和其他…东西)之后,我尝试在不使用可变变量的情况下重现以下场景(改编自计算点击次数的简单UI): 让可变计数=1 让increment()=count如果不使用可变变量,则可以使用ref变量。使用它,您的代码将如下所示 let count = ref 1 let increment() = count := !count + 1 虽然我使用mutable比ref更频繁,但我对这两个变量并不挑剔。我发现这也是一个很好的读物,可以很好地理解这两个变量之间的差异。变异变量的函数替代

在阅读了状态单子(和其他…东西)之后,我尝试在不使用可变变量的情况下重现以下场景(改编自计算点击次数的简单UI):

让可变计数=1

让increment()=count如果不使用可变变量,则可以使用ref变量。使用它,您的代码将如下所示

let count = ref 1
let increment() = count := !count + 1

虽然我使用mutable比ref更频繁,但我对这两个变量并不挑剔。我发现这也是一个很好的读物,可以很好地理解这两个变量之间的差异。

变异变量的函数替代方法是从函数返回一个更新的值。有状态计算可以由函数建模,这些函数获取状态的当前值,并返回一对包含结果和状态的更新值。您可以在F#中定义这样的类型,如

这需要一个有状态计算和一个函数来构造一个新的计算,给出第一个计算的结果值。然后构造一个复合计算,该计算将运行第一次计算,使用该值构造下一次计算,然后使用第一次计算返回的中间状态运行给定的计算

这将形成一个monad,因此您可以创建一个计算表达式,并使用它以更方便的语法进行有状态计算:

type StateBuilder() = 
    member this.Return(x) = returnState x
    member this.Bind(s, f) = bindState s f
    member this.ReturnFrom(s: State<_,_>) = s

let state = StateBuilder()

let modifyState f = state {
    let! s = getState
    let s' = f s
    return! (putState s')
}

“我不成功”是什么意思?发生了什么事,或者你犯了什么错误?简单评论一下:我所知道的所有实用的相关语言(当然包括Haskell)都允许你在某个时候改变某些状态(并更新你的数据库)纯语言的想法。就是尽可能地将其扩展到应用程序的边界(在Haskell中,这可能是
main
中臭名昭著的
IO
类型)-F不纯粹,通常被认为是可以的-在您的示例中,大多数F#er不会使用StateMonad(因为你不能在没有人的情况下构建MonadStack。重写这在大多数情况下都不是一个选项)
ref
在语义上也有同样的效果;只是编译器对它的处理有点不同(在F#4中不再需要)。对落选者:没有解释为什么的落选是毫无帮助和毫无意义的。只是不要这样做。在帖子中添加了一个链接,说明他们之间的差异,即使他们之间有很多相似之处。这就是为什么要进行落选吗?我相信落选是因为在上下文中理解了可变性这一事实函数式编程,而不是特定的
mutable
关键字。因此答案非常误导,因为它可能会让一些人相信
ref
是避免易变性的正确方法。@TeaDrivenDev虽然我基本上同意你应该给出一些提示,说明你为什么否决它,但这是你不需要的元-事实上我t的设计是为了让你可以私下进行向下投票和向上投票-如果你想(并且需要一些向下投票),请转到META并讨论(再次;))我如何将其合并到我的原始示例中,单击按钮将修改状态?
type State<'s, 'a> = S of ('s -> ('s * 'a))
let returnState x = S (fun s -> (s, x))
let runState (S(f)) s = f s
let putState s = S (fun _ -> (s, ()))
let getState<'s, 'a> = S (fun (s: 's) -> (s, s))
let bindState<'s, 'a, 'b> (S(sf): State<'s, 'a>) (f : 'a -> State<'s, 'b>) = S (fun s ->
        let (s', r) = sf s
        let (S(sf')) = f r
        sf' s')
type StateBuilder() = 
    member this.Return(x) = returnState x
    member this.Bind(s, f) = bindState s f
    member this.ReturnFrom(s: State<_,_>) = s

let state = StateBuilder()

let modifyState f = state {
    let! s = getState
    let s' = f s
    return! (putState s')
}
let incState = modifyState ((+)1)