Skip to content

Instantly share code, notes, and snippets.

@SchlenkR
Forked from nickcowle/ApplicativeBuilder.fsx
Created March 13, 2020 11:52
Show Gist options
  • Save SchlenkR/e58199cff7246a6317098d98eeb8012e to your computer and use it in GitHub Desktop.
Save SchlenkR/e58199cff7246a6317098d98eeb8012e to your computer and use it in GitHub Desktop.
type 'a Foo = Foo of 'a
module Foo =
let ofValue (a : 'a) : 'a Foo = Foo a
let apply (a : 'a Foo) (f : ('a -> 'b) Foo) : 'b Foo =
let (Foo f) = f
let (Foo a) = a
Foo (f a)
let map (f : 'a -> 'b) (a : 'a Foo) : 'b Foo =
ofValue f |> apply a
let map2 (f : 'a -> 'b -> 'c) (a : 'a Foo) (b : 'b Foo) : 'c Foo =
map f a |> apply b
type FooBuilder () =
member __.For (foo, f) =
Foo.map f foo
member __.Yield (a : 'a) : 'a =
a
member __.Return (a : 'a) : 'a =
a
[<CustomOperation("apply", IsLikeZip = true)>]
member __.Zip ((), foo : 'a Foo, f : unit -> 'a -> 'b) : 'b Foo =
Foo.map (f ()) foo
[<CustomOperation("also", IsLikeZip = true)>]
member __.Zip2 (foo1 : 'a Foo, foo2 : 'b Foo, f : 'a -> 'b -> 'c) : 'c Foo =
Foo.map2 f foo1 foo2
let foo = FooBuilder ()
let myFoo = Foo.ofValue 1234
let myFoo2 = Foo.ofValue false
let myFoo3 = Foo.ofValue "Hello"
let test : string Foo =
foo {
apply i in myFoo
also b in myFoo2
also s in myFoo3
return if b then sprintf "%i" i else s
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment