我正在研究单子构图。虽然我已经了解了如何构成for loop
和Async
,就像here一样,但我在构想Continuation Monad和State Monad方面还是很努力。
从基本的Result
实现开始,并从State Monad
开始进行测试:
State-based-Stack
然后还具有Continuation Monad的基本实现:
type State<'State,'Value> = State of ('State -> 'Value * 'State)
module State =
let runS (State f) state = f state
let returnS x =
let run state =
x, state
State run
let bindS f xS =
let run state =
let x, newState = runS xS state
runS (f x) newState
State run
let getS =
let run state = state, state
State run
let putS newState =
let run _ = (), newState
State run
type StateBuilder()=
member __.Return(x) = returnS x
member __.Bind(xS,f) = bindS f xS
let state = new StateBuilder()
module Stack =
open State
type Stack<'a> = Stack of 'a list
let popStack (Stack contents) =
match contents with
| [] -> failwith "Stack underflow"
| head::tail ->
head, (Stack tail)
let pushStack newTop (Stack contents) =
Stack (newTop::contents)
let emptyStack = Stack []
let getValue stackM =
runS stackM emptyStack |> fst
let pop() = state {
let! stack = getS
let top, remainingStack = popStack stack
do! putS remainingStack
return top }
let push newTop = state {
let! stack = getS
let newStack = pushStack newTop stack
do! putS newStack
return () }
我正在尝试这样写:
type Cont<'T,'r> = (('T -> 'r) -> 'r)
module Continuation =
let returnCont x = (fun k -> k x)
let bindCont f m = (fun k -> m (fun a -> f a k))
let delayCont f = (fun k -> f () k)
let runCont (c:Cont<_,_>) cont = c cont
let callcc (f: ('T -> Cont<'b,'r>) -> Cont<'T,'r>) : Cont<'T,'r> =
fun cont -> runCont (f (fun a -> (fun _ -> cont a))) cont
type ContinuationBuilder() =
member __.Return(x) = returnCont x
member __.ReturnFrom(x) = x
member __.Bind(m,f) = bindCont f m
member __.Delay(f) = delayCont f
member this.Zero () = this.Return ()
let cont = new ContinuationBuilder()
尽管这可以编译并且看起来正确(就机械地遵循步骤组成而言),但我无法实现module StateK =
open Continuation
let runSK (State f) state = cont { return f state }
let returnSK x = x |> State.returnS |> returnCont
let bindSK f xSK = cont {
let! xS = xSK
return (State.bindS f xS) }
let getSK k =
let run state = state, state
State run |> k
let putSK newState = cont {
let run _ = (), newState
return State run }
type StateContinuationBuilder() =
member __.Return(x) = returnSK x
member __.ReturnFrom(x) = x
member __.Bind(m,f) = bindSK f m
member this.Zero () = this.Return ()
let stateK = new StateContinuationBuilder()
。
到目前为止,我有这个,但这是完全错误的:
StateK-based-Stack
有些帮助可以帮助您理解为什么以及为什么如此。 如果有您可以指向的阅读材料,它也可以使用。
*********在AMieres评论后进行编辑**************
新的module StackCont =
open StateK
type Stack<'a> = Stack of 'a list
let popStack (Stack contents) = stateK {
match contents with
| [] -> return failwith "Stack underflow"
| head::tail ->
return head, (Stack tail) }
let pushStack newTop (Stack contents) = stateK {
return Stack (newTop::contents) }
let emptyStack = Stack []
let getValue stackM = stateK {
return runSK stackM emptyStack |> fst }
let pop() = stateK {
let! stack = getSK
let! top, remainingStack = popStack stack
do! putSK remainingStack
return top }
let push newTop = stateK {
let! stack = getSK
let! newStack = pushStack newTop stack
do! putSK newStack
return () }
实现试图保持签名正确。
bindSK
尽管如此,类型type StateK<'State,'Value,'r> = Cont<State<'State,'Value>,'r>
module StateK =
let returnSK x : StateK<'s,'a,'r> = x |> State.returnS |> Continuation.returnCont
let bindSK (f : 'a -> StateK<'s,'b,'r>)
(m : StateK<'s,'a,'r>) : StateK<'s,'b,'r> =
(fun cont ->
m (fun (State xS) ->
let run state =
let x, newState = xS state
(f x) (fun (State k) -> k newState)
cont (State run)))
已被约束为'r
我已经尝试删除约束,但是还无法做到
答案 0 :(得分:2)
我也无法解决它。
我只能给您一个提示,可以帮助您更好地理解它。将通用类型替换为常规类型,例如:
let bindSK (f : 'a -> StateK<'s,'b,'r>)
(m : StateK<'s,'a,'r>) : StateK<'s,'b,'r> =
(fun cont ->
m (fun (State xS) ->
let run state =
let x, newState = xS state
(f x) (fun (State k) -> k newState)
cont (State run)))
将's
替换为string
,将'a
替换为int
,将'b
替换为char
,将'r
替换为{{1} }
float
那样更容易看到
let bindSK (f : int -> StateK<string,char,float>)
(m : StateK<string,int,float>) : StateK<string,char,float> =
(fun cont ->
m (fun (State xS) ->
let run state =
let x, newState = xS state
(f x) (fun (State k) -> k newState)
cont (State run)))
是k
string -> char * string
是k newState
char * string
是(f x)
(State<string,char> -> float) -> float
是m
因此它们不兼容。
答案 1 :(得分:2)
我阅读了更多内容,结果发现,“ ContinuousState”的正确类型是's -> Cont<'a * 's, 'r>
因此,我使用此签名重新实现了StateK
单子,并且全部自然飞行。
这是代码(为完整性起见,我添加了mapSK和applySK):
type Cont<'T,'r> = (('T -> 'r) -> 'r)
let returnCont x = (fun k -> k x)
let bindCont f m = (fun k -> m (fun a -> f a k))
let delayCont f = (fun k -> f () k)
type ContinuationBuilder() =
member __.Return(x) = returnCont x
member __.ReturnFrom(x) = x
member __.Bind(m,f) = bindCont f m
member __.Delay(f) = delayCont f
member this.Zero () = this.Return ()
let cont = new ContinuationBuilder()
type StateK<'State,'Value,'r> = StateK of ('State -> Cont<'Value * 'State, 'r>)
module StateK =
let returnSK x =
let run state = cont {
return x, state
}
StateK run
let runSK (StateK fSK : StateK<'s,'a,'r>) (state : 's) : Cont<'a * 's, _> = cont {
return! fSK state }
let mapSK (f : 'a -> 'b) (m : StateK<'s,'a,'r>) : StateK<'s,'b,'r> =
let run state = cont {
let! x, newState = runSK m state
return f x, newState }
StateK run
let bindSK (f : 'a -> StateK<'s,'b,'r>) (xSK : StateK<'s,'a,'r>) : (StateK<'s,'b,'r>) =
let run state = cont {
let! x, newState = runSK xSK state
return! runSK (f x) newState }
StateK run
let applySK (fS : StateK<'s, 'a -> 'b, 'r>) (xSK : StateK<'s,'a,'r>) : StateK<'s,'b,'r> =
let run state = cont {
let! f, s1 = runSK fS state
let! x, s2 = runSK xSK s1
return f x, s2 }
StateK run
let getSK =
let run state = cont { return state, state }
StateK run
let putSK newState =
let run _ = cont { return (), newState }
StateK run
type StateKBuilder() =
member __.Return(x) = returnSK x
member __.ReturnFrom (x) = x
member __.Bind(xS,f) = bindSK f xS
member this.Zero() = this.Return ()
let stateK = new StateKBuilder()
module StackCont =
open StateK
type Stack<'a> = Stack of 'a list
let popStack (Stack contents) =
match contents with
| [] -> failwith "Stack underflow"
| head::tail ->
head, (Stack tail)
let pushStack newTop (Stack contents) =
Stack (newTop::contents)
let emptyStack = Stack []
let getValueSK stackM = cont {
let! f = runSK stackM emptyStack
return f |> fst }
let pop() = stateK {
let! stack = getSK
let top, remainingStack = popStack stack
do! putSK remainingStack
return top }
let push newTop = stateK {
let! stack = getSK
let newStack = pushStack newTop stack
do! putSK newStack
return () }
open StateK
open StackCont
let helloWorldSK = (fun () -> stateK {
do! push "world"
do! push "hello"
let! top1 = pop()
let! top2 = pop()
let combined = top1 + " " + top2
return combined
})
let helloWorld = getValueSK (helloWorldSK ()) id
printfn "%s" helloWorld
答案 2 :(得分:0)
据我所知,我又给了它一炮而红,实际上是Cont · State
:
type State<'State,'Value> = State of ('State -> 'Value * 'State)
type StateK<'s,'T> = ((State<'s,'T> -> 'T * 's) -> 'T * 's)
let returnCont x : StateK<'s,'a> = (fun k -> k x)
let returnSK x =
let run state =
x, state
State run |> returnCont
let runSK (f : ((State<'s,'b> -> 'b * 's) -> 'b * 's)) state = f (fun (State xS) -> xS state)
let bindSK (f : 'a -> StateK<'s,'b>) (xS :StateK<'s,'a>) : StateK<'s,'b> =
let run state =
let x, newState = runSK xS state
runSK (f x) newState
returnCont (State run) // is this right? as far as I cant tell the previous (next?) continuation is encapsulated on run so this is only so the return type conforms with what is expected of a bind
let getSK k =
let run state = state, state
State run |> k
let putSK newState =
let run _ = (), newState
State run |> returnCont
type StateKBuilder()=
member __.Return(x) = returnSK x
member __.Bind(xS,f) = bindSK f xS
let stateK = new StateKBuilder()
type Stack<'a> = Stack of 'a list
let popStack (Stack contents) =
match contents with
| [] -> failwith "Stack underflow"
| head::tail ->
head, (Stack tail)
let pushStack newTop (Stack contents) =
Stack (newTop::contents)
let emptyStack = Stack []
let getValueS stackM =
runSK stackM emptyStack |> fst
let pop () = stateK {
let! stack = getSK
let top, remainingStack = popStack stack
do! putSK remainingStack
return top }
let push newTop = stateK {
let! stack = getSK
let newStack = pushStack newTop stack
do! putSK newStack
return () }
let helloWorldSK = (fun k -> stateK {
do! push "world"
do! push "hello"
let! top1 = pop()
let! top2 = pop()
let combined = top1 + " " + top2
return combined
})
let helloWorld = getValueS (helloWorldSK id)
printfn "%s" helloWorld