RosettaCodeData/Task/Man-or-boy-test/F-Sharp/man-or-boy-test-2.fs
2023-07-01 13:44:08 -04:00

55 lines
1.3 KiB
FSharp

type Tramp<'t> =
| Delay of (unit -> Tramp<'t>)
| Bind of Tramp<'t> * ('t -> Tramp<'t>)
| Return of 't
| ReturnFrom of Tramp<'t>
type Tramp() =
member this.Delay(f) = Delay f
member this.Bind(x, f) = Bind(x, f)
member this.Return(x) = Return x
member this.ReturnFrom(x) = ReturnFrom x
let tramp = Tramp()
let run (tr : Tramp<'t>) =
let rec loop tr stack =
match tr with
| Delay f -> loop (f()) stack
| Bind(x, f) -> loop x (f :: stack)
| Return x ->
match stack with
| [] -> x
| f :: stack' -> loop (f x) stack'
| ReturnFrom tr -> loop tr stack
loop tr []
[<EntryPoint>]
let main (args : string[]) =
let k = int(args.[0])
let l x = fun() -> Return x
tramp {
let rec a k x1 x2 x3 x4 x5 =
tramp {
if k <= 0 then
let! x4' = x4()
let! x5' = x5()
return x4' + x5'
else
let k = ref k
let rec b() =
tramp {
k := !k - 1
return! a !k b x1 x2 x3 x4
}
return! b()
}
return! a k (l 1) (l -1) (l -1) (l 1) (l 0)
}
|> run
|> printfn "%A"
0