Created
March 9, 2016 15:08
-
-
Save hodzanassredin/40c63c286466bff38516 to your computer and use it in GitHub Desktop.
solving expression problem in fsharp with object algebras
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ExpAlg<'a> = | |
abstract member lit: int -> 'a | |
abstract member Add: 'a -> 'a -> 'a | |
type Algebra<'alg,'a> = 'alg -> 'a | |
let lit i (alg:ExpAlg<'a>) = alg.lit i | |
let add a b (alg:ExpAlg<'a>) = alg.Add a b | |
type AlgebraBuilder() = | |
member inline x.Return(v) : Algebra<'alg,'r> = fun r -> v | |
member inline x.ReturnFrom(v) : Algebra<'alg,'r> = v | |
member inline x.Bind(rm1:Algebra<'alg,'r>, f:'r -> Algebra<'alg,'r2>) : Algebra<'alg,'r2> = | |
fun a -> let r = rm1 a | |
f r a | |
let algebra = AlgebraBuilder() | |
let e1() = algebra{ | |
let! a = lit 1 | |
let! b = lit 2 | |
let! c = lit 3 | |
let! bc = add b c | |
return! add a bc | |
} | |
let e1b (alg:ExpAlg<'a>) = | |
alg.Add (alg.lit 1) (alg.Add (alg.lit(1)) (alg.lit(1))) | |
type Eval = | |
abstract member eval: unit -> int | |
type EvalExp () = | |
interface ExpAlg<Eval> with | |
member this.Add x y = | |
{new Eval with member this.eval() = x.eval() + y.eval() } | |
member this.lit i = | |
{new Eval with member this.eval() = i } | |
printfn "eval e1 %A" <| (e1 () (EvalExp())).eval() | |
type MulAlg<'a> = | |
inherit ExpAlg<'a> | |
abstract member Mul: 'a -> 'a -> 'a | |
let mul a b (alg:MulAlg<'a>) = alg.Mul a b | |
let e2() = algebra{ | |
let! a = lit 1 | |
let! b = lit 2 | |
let! c = lit 3 | |
let! bc = add b c | |
return! mul a bc | |
} | |
type EvalMulExp () = | |
inherit EvalExp() | |
interface MulAlg<Eval> with | |
member this.Mul x y = | |
{new Eval with member this.eval() = x.eval() * y.eval() } | |
printfn "eval e2 %A" <| (e2 () (EvalMulExp())).eval() | |
type View = | |
abstract member view: unit -> string | |
type ViewExp () = | |
interface ExpAlg<View> with | |
member this.Add x y = | |
{new View with member this.view() = sprintf "(%s + %s)" <| x.view() <| y.view() } | |
member this.lit i = | |
{new View with member this.view() = i.ToString() } | |
type ViewMulExp () = | |
inherit ViewExp() | |
interface MulAlg<View> with | |
member this.Mul x y = | |
{new View with member this.view() = sprintf "(%s * %s)" <| x.view() <| y.view() } | |
printfn "view e1 %A" <| (e1 () (ViewExp())).view() | |
printfn "view e2 %A" <| (e2 () (ViewMulExp())).view() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment