How can I implement Stateful Builder with CustomOperations and some

I am trying to figure out how to create a stateful constructor and I cannot get around some compiler errors

type Movement =
    | Left of int
    | Right of int

type MovementState = Movement list -> Movement list

type MovementBuilder () =
    member x.Zero () : MovementState = id
    member __.Return x : MovementState = id
    member __.Bind(m: MovementState, f: MovementState ) = fun v -> f (m v)

    [<CustomOperation("left", MaintainsVariableSpaceUsingBind = true)>]
    member x.Left(ms, value) = x.Bind(ms, fun xs -> xs @ [Left value])

    [<CustomOperation("right", MaintainsVariableSpaceUsingBind = true)>]
    member x.Right(ms, value) = x.Bind(ms, fun xs -> xs @ [Right value])

let movement = MovementBuilder()

[]
|> movement {
    left 10
    right 20
}
|> printfn "list %A"
//prints [Left 10; Right 20]

However, now I want to enter let!or yieldto add additional elements without going through certain CustomOperations so that, for example, I can do the following

[]
|> movement {
    left 10
    let! _ = (fun xs -> xs @ [Right 99])
    //I also tried naming the value
    //let! x = (fun xs -> xs @ [Right 99])
    //I also tried wrapping it into another function ...
    //let! x = fun () -> (fun xs -> xs @ [Right 99])
    right 20
}
|> printfn "list %A"
//Should print [Left 10; Right 99; Right 20]

Any help is appreciated. Bonus karma will be sent to explain how the compiler rewrites this to the Binds series

thank

+4
source share
1 answer

, , , "" - ( Async < 'a > "a" ).

, , , unit, bind member __.Bind(m: MovementState, f : unit -> MovementState).

do! movestates . , , , ! let! , "" .

, :

type PTD = ProvidedTypeDefinition -> ProvidedTypeDefinition

type ProvidedTypeBuilder () =
    member __.Zero () : PTD =
        id
    member __.Return _ : PTD =
        id
    member __.Bind(m, f : unit -> PTD) =
        fun ptd -> (f ()) (m ptd)
    member x.Combine(m1 : PTD, m2 : PTD) : PTD =
        x.Bind(m1, fun () -> m2)

    [<CustomOperation("addMember", MaintainsVariableSpaceUsingBind = true)>]
    member x.AddMember(ptd, member') =
        let func =
          fun (instance : ProvidedTypeDefinition) ->
              instance.AddMember member'
              instance
        x.Bind(ptd, fun () -> func)

, do!, - , :

let ptd = ProvidedTypeBuilder()

let test =
    ptd {
        addMember (ProvidedProperty("MyProp", typeof<string>))
        do! (fun ptd -> ptd.AddObsoleteAttribute("Hey, don't use this anymore"); ptd)
    }
+3

Source: https://habr.com/ru/post/1679225/


All Articles