这个问题与这个问题有关
我有一个状态单子。对象提供了OOD 策略模式update
中的功能。
- 拥有一个对象的选择是,在实际的生产代码中,该类提供一组操作,所有操作都通过 monad 共享状态。继承帮助我扩展了基本功能并进一步定制了提供操作的类。
- 在类中使用 monad 而不是可变属性的选择是,通过正确使用泛型,monad 正在帮助我抽象化并更加灵活地处理必须在计算中作为“状态”携带的变量/信息。
我有一个简单的玩具示例:
/////////////////////////////////////////////////////////////////////////////////////
// Definition of the state
/////////////////////////////////////////////////////////////////////////////////////
type StateFunc<'State, 'T> = 'State -> 'T * 'State
/////////////////////////////////////////////////////////////////////////////////////
// Definition of the State monad type
/////////////////////////////////////////////////////////////////////////////////////
type StateMonadBuilder<'State>() =
// M<'T> -> M<'T>
member b.ReturnFrom a : StateFunc<'State, 'T> = a
// 'T -> M<'T>
member b.Return a : StateFunc<'State, 'T> = ( fun s -> a, s)
// M<'T> * ('T -> M<'U>) -> M<'U>
member b.Bind(p : StateFunc<_, 'T>, rest : 'T -> StateFunc<_,_>) : StateFunc<'State, 'U> =
(fun s ->
let a, s' = p s
rest a s')
// Getter for the whole state, this type signature is because it passes along the state & returns the state
member b.getState : StateFunc<'State, _> = (fun s -> s, s)
// Setter for the state
member b.putState (s:'State) : StateFunc<'State, _> = (fun _ -> (), s)
let runState f init = f init
/////////////////////////////////////////////////////////////////////////////////////
// STRATEGY PATTERN
/////////////////////////////////////////////////////////////////////////////////////
let state = StateMonadBuilder<int> ()
// DoubleFunctOne defines standard operations that remain always the same
type Strategy (aFunction) =
member this.Update (x: int) = state {
let! currState = state.getState
let processedx = aFunction x
do! state.putState (currState + x) }
// Create a function that customizes the strategy
let myFunction x =
2 * x
// Customize the strategy with the desired function:
let strategy = Strategy (myFunction)
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Update recursively
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// ?? How to run update recursively ??
let result initialCondition =
initialCondition
|> (for i = 10 to 100 do
yield state { do! strategy.Update i } )
我的目标是应用初始条件、获取数据并递归地启动(在一个循环或for
一个while
循环甚至一些函数操作中)由strategy
. 与 monad 一起工作,我不知道该怎么做。
谢谢你。
计算表达式
受@kvb 答案的启发,我for
在计算表达式中添加了一个方法。
// Loops through seqnc of numbers that constitute an input to func
member b.For (seqnc:_ List, func) =
seqnc
|> List.map (fun item -> func item)
|> List.reduce (fun acc item ->
(fun s ->
let _, s' = acc s
item s' ) )
我进行了一些测试,我的印象是这个有效。谢谢。