Skip to content

Instantly share code, notes, and snippets.

@t0yv0
Created September 23, 2009 22:39
Show Gist options
  • Save t0yv0/192353 to your computer and use it in GitHub Desktop.
Save t0yv0/192353 to your computer and use it in GitHub Desktop.
another take on F# monads
module Monad =
type M<'T,'B when 'B :> Sig<'B>> =
interface end
and Sig<'B when 'B :> Sig<'B>> =
abstract member Return<'X> : 'X -> M<'X,'B>
abstract member Bind<'X,'Y> :
M<'X,'B> -> ('X -> M<'Y,'B>) -> M<'Y,'B>
type Make<'B when 'B :> Sig<'B>
and 'B : (new : unit -> 'B)> () =
static let m = new 'B () :> Sig<'B>
member this.Bind (x, f) =
m.Bind x f
member this.Return x =
m.Return x
member this.Sequence list =
match list with
| [] ->
m.Return []
| x :: xs ->
m.Bind x <| fun x ->
let f xs = m.Return (x :: xs)
let xs = this.Sequence xs
m.Bind xs f
module Maybe =
type T<'T> =
| Just of 'T
| Nothing
interface Monad.M<'T, Monad>
and Monad () =
interface Monad.Sig<Monad> with
member this.Return x =
Just x :> _
member this.Bind x f =
match x :?> _ with
| Just x -> f x
| Nothing -> Nothing :> _
let Do = new Monad.Make<Monad>()
module List =
type T<'T> = { T : list<'T> } with
interface Monad.M<'T, Monad>
and Monad () =
interface Monad.Sig<Monad> with
member this.Return x =
Conv.OfList [x] :> _
member this.Bind x f =
Conv.ToList (x :?> _)
|> List.collect (fun x -> Conv.ToList (f x :?> _))
|> Conv.OfList
:> _
and Conv =
static member ToList<'T> (x : T<'T>) : list<'T> = x.T
static member OfList<'T> (x : list<'T>) : T<'T> = { T = x }
let Do = new Monad.Make<Monad>()
Maybe.Do {
let! x = Maybe.Just 1
return! Maybe.Do.Sequence [Maybe.Just x; Maybe.Just (x + 1)]
}
|> printfn "%A"
List.Do {
let list x = List.Conv.OfList x
let! x = list [1; 2; 3]
return! List.Do.Sequence [list [1; 2]; list [3; 4]]
}
|> printfn "%A"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment