Monad的组成(续·状态)

时间:2019-01-11 19:53:05

标签: functional-programming f# continuations state-monad category-theory

我正在研究单子构图。虽然我已经了解了如何构成for loopAsync,就像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 我已经尝试删除约束,但是还无法做到

3 个答案:

答案 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 * stringk newState
  • char * string(f x)
  • (State<string,char> -> float) -> floatm

因此它们不兼容。

答案 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