10 people like it.
Like the snippet!
Functor => Applicative => Monad
Yet another attempt of mine to "haskellify" my F# coding.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
|
#r "FSharp.PowerPack.dll"
open System
// Generic container of 'T
// Also parameterized by 'TypeClass : (new : unit -> 'TypeClass) to implicit get a 'TypeClass instance (like passing the type class dictionary)
// The idea is to encode Type Classes with subtype polymorphism and OOP Classes
type Generic<'T, 'TypeClass when 'TypeClass : (new : unit -> 'TypeClass)> = interface end
type [<AbstractClass>] FunctorClass<'FunctorClass when 'FunctorClass :> FunctorClass<'FunctorClass>
and 'FunctorClass : (new : unit -> 'FunctorClass)>() =
abstract FMap<'T, 'R> : ('T -> 'R) -> Generic<'T, 'FunctorClass> -> Generic<'R, 'FunctorClass>
type [<AbstractClass>] ApplicativeClass<'ApplicativeClass when 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass>
and 'ApplicativeClass : (new : unit -> 'ApplicativeClass)>() =
inherit FunctorClass<'ApplicativeClass>()
// abstract methods
abstract Pure<'T> : 'T -> Generic<'T, 'ApplicativeClass>
abstract Apply<'T, 'R> : Generic<'T -> 'R, 'ApplicativeClass> -> Generic<'T, 'ApplicativeClass> -> Generic<'R, 'ApplicativeClass>
// Functor default implementation
override this.FMap<'T, 'R> (f : 'T -> 'R) (fa : Generic<'T, 'ApplicativeClass>) : Generic<'R, 'ApplicativeClass> =
this.Apply (this.Pure f) fa
type [<AbstractClass>] MonadClass<'MonadClass when 'MonadClass :> MonadClass<'MonadClass>
and 'MonadClass : (new : unit -> 'MonadClass)>() =
inherit ApplicativeClass<'MonadClass>()
// abstract methods
abstract Return<'T> : 'T -> Generic<'T, 'MonadClass>
abstract Bind<'T, 'R> : Generic<'T, 'MonadClass> * ('T -> Generic<'R, 'MonadClass>) -> Generic<'R, 'MonadClass>
// Default implementations
member this.Then<'T, 'R> ((ma : Generic<'T, 'MonadClass>), (mb : Generic<'R, 'MonadClass>)) : Generic<'R, 'MonadClass> =
this.Bind(ma, fun _ -> mb)
// Applicative default implementation
override this.Pure<'T> (value : 'T) : Generic<'T, 'MonadClass> = this.Return value
override this.Apply<'T, 'R> (mf : Generic<'T -> 'R, 'MonadClass>) (ma : Generic<'T, 'MonadClass>) : Generic<'R, 'MonadClass> =
this.Bind(mf, fun f -> this.Bind(ma, fun a -> this.Pure (f a)))
// Maybe Monad
type Maybe<'T> = None | Some of 'T with
interface Generic<'T, MaybeClass>
and MaybeClass() =
inherit MonadClass<MaybeClass>() with
override this.Return<'T>(v : 'T) = Some v :> _
override this.Bind<'T, 'R> ((m : Generic<'T, MaybeClass>), (f : ('T -> Generic<'R, MaybeClass>))) : Generic<'R, MaybeClass> =
match m :?> _ with
| Some v -> f v
| None -> None :> _
let maybe = new MaybeClass() :> MonadClass<MaybeClass>
// List Monad
type ListMonadGeneric<'T> = ListMonadGeneric of LazyList<'T> with
interface Generic<'T, ListMonadClass>
and ListMonadClass() =
inherit MonadClass<ListMonadClass>() with
override this.Return<'T>(v : 'T) = ListMonadGeneric (LazyList.ofList [v]) :> _
override this.Bind<'T, 'R> ((m : Generic<'T, ListMonadClass>), (f : ('T -> Generic<'R, ListMonadClass>))) : Generic<'R, ListMonadClass> =
let (ListMonadGeneric list) = m :?> _ in ListMonadGeneric (LazyList.ofSeq <| Seq.collect (fun v -> let (ListMonadGeneric list') = (f v) :?> _ in list') list) :> _
// ZipList Applicative Functor
type ListAppGeneric<'T> = ListAppGeneric of LazyList<'T> with
interface Generic<'T, ListApplicativeClass>
and ListApplicativeClass() =
inherit ApplicativeClass<ListApplicativeClass>() with
override this.Pure<'T> (v : 'T) = ListAppGeneric (LazyList.repeat v) :> _
override this.Apply<'T, 'R> (ff : Generic<'T -> 'R, ListApplicativeClass>) (fa : Generic<'T, ListApplicativeClass>) : Generic<'R, ListApplicativeClass> =
let (ListAppGeneric listf) = ff :?> _ in let (ListAppGeneric list) = fa :?> _ in ListAppGeneric (LazyList.map (fun (f, a) -> f a) (LazyList.zip listf list)) :> _
// Generic functions that operate over all Applicative Funtors
[<AutoOpen>]
module ApplicativeModule =
let pure<'T, 'ApplicativeClass when 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass>
and 'ApplicativeClass : (new : unit -> 'ApplicativeClass)>
(v : 'T) : Generic<'T, 'ApplicativeClass> =
(new 'ApplicativeClass()).Pure v
let apply<'T, 'R, 'ApplicativeClass when 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass>
and 'ApplicativeClass : (new : unit -> 'ApplicativeClass)>
(ff : Generic<'T -> 'R, 'ApplicativeClass>) (fa : Generic<'T, 'ApplicativeClass>) : Generic<'R, 'ApplicativeClass> =
(new 'ApplicativeClass()).Apply ff fa
let (<*>) ff fa = apply ff fa
let ($) f fa = pure f <*> fa
// Monoidal - pair
let (<.>) fa fb = (fun a b -> (a, b)) $ fa <*> fb
// Generic functions that operate over all Monads
[<AutoOpen>]
module MonadModule =
let unit<'T, 'MonadClass when 'MonadClass :> MonadClass<'MonadClass>
and 'MonadClass : (new : unit -> 'MonadClass)>
(v : 'T) : Generic<'T, 'MonadClass> =
(new 'MonadClass()).Return v
let bind<'T, 'R, 'MonadClass when 'MonadClass :> MonadClass<'MonadClass>
and 'MonadClass : (new : unit -> 'MonadClass)>
(m : Generic<'T, 'MonadClass>) (f : 'T -> Generic<'R, 'MonadClass>) : Generic<'R, 'MonadClass> =
(new 'MonadClass()).Bind(m, f)
let (>>=) = bind
let (>>) ma mb = ma >>= fun _ -> mb
let rec sequence (list : Generic<'T, 'MonadClass> list) : Generic<'T list, 'MonadClass> =
match list with
| [] -> unit []
| m :: ms -> m >>= fun v -> sequence ms >>= fun vs -> unit (v :: vs)
let mapM (f : 'T -> Generic<'R, 'MonadClass>) (list : 'T list) : Generic<'R list, 'MonadClass> =
(sequence << List.map f) list
let rec filterM (p : 'T -> Generic<bool, 'MonadClass>) (list : 'T list) : Generic<'T list, 'MonadClass> =
match list with
| [] -> unit []
| x :: xs -> p x >>= fun b -> filterM p xs >>= fun ys -> if b then unit (x :: ys) else unit ys
// Examples
// Maybe Monad Examples
maybe { return 1 } >>= fun k -> maybe { return k + 1 } // Some 2
maybe { let! k = maybe { return 1 } in return k + 1 } // Some 2
sequence [maybe { return 1 }; maybe { return 2 }; maybe { return 3 }] // Some [1; 2; 3]
mapM (fun v -> maybe { return v * 2 }) [1 .. 5] // Some [2; 4; 6; 8]
filterM (fun v -> maybe { return v % 2 = 0 }) [1..5] // Some [2; 4]
// ZipList example
let rec transpose (listoflist : LazyList<LazyList<'T>>) : Generic<LazyList<'T>, ListApplicativeClass> =
match listoflist with
| LazyList.Nil -> pure LazyList.empty
| LazyList.Cons (xs, xss) -> LazyList.cons $ (ListAppGeneric xs) <*> transpose xss
[[1; 2; 3]; [4; 5; 6]]
|> LazyList.ofList
|> LazyList.map LazyList.ofList
|> transpose // result: ListAppGeneric (seq [seq [1; 4]; seq [2; 5]; seq [3; 6]])
// List Monad example
let onetoten = ListMonadGeneric (LazyList.ofList [1..3])
(fun a b -> sprintf "%d * %d = %d" a b (a * b)) $ onetoten <*> onetoten
// result: ListMonadGeneric (seq ["1 * 1 = 1"; "1 * 2 = 2"; "1 * 3 = 3"; "2 * 1 = 2"; ...])
|
namespace System
type Generic<'T,'TypeClass (requires default constructor)>
Full name: Script.Generic<_,_>
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
Multiple items
type AbstractClassAttribute =
inherit Attribute
new : unit -> AbstractClassAttribute
Full name: Microsoft.FSharp.Core.AbstractClassAttribute
--------------------
new : unit -> AbstractClassAttribute
Multiple items
type FunctorClass<'FunctorClass (requires 'FunctorClass :> FunctorClass<'FunctorClass> and default constructor)> =
new : unit -> FunctorClass<'FunctorClass>
abstract member FMap : ('T -> 'R) -> Generic<'T,'FunctorClass> -> Generic<'R,'FunctorClass>
Full name: Script.FunctorClass<_>
--------------------
new : unit -> FunctorClass<'FunctorClass>
abstract member FunctorClass.FMap : ('T -> 'R) -> Generic<'T,'FunctorClass> -> Generic<'R,'FunctorClass>
Full name: Script.FunctorClass`1.FMap
Multiple items
type ApplicativeClass<'ApplicativeClass (requires 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass> and default constructor)> =
inherit FunctorClass<'ApplicativeClass>
new : unit -> ApplicativeClass<'ApplicativeClass>
abstract member Apply : Generic<('T -> 'R),'ApplicativeClass> -> Generic<'T,'ApplicativeClass> -> Generic<'R,'ApplicativeClass>
abstract member Pure : 'T -> Generic<'T,'ApplicativeClass>
override FMap : f:('T -> 'R) -> fa:Generic<'T,'ApplicativeClass> -> Generic<'R,'ApplicativeClass>
Full name: Script.ApplicativeClass<_>
--------------------
new : unit -> ApplicativeClass<'ApplicativeClass>
abstract member ApplicativeClass.Pure : 'T -> Generic<'T,'ApplicativeClass>
Full name: Script.ApplicativeClass`1.Pure
abstract member ApplicativeClass.Apply : Generic<('T -> 'R),'ApplicativeClass> -> Generic<'T,'ApplicativeClass> -> Generic<'R,'ApplicativeClass>
Full name: Script.ApplicativeClass`1.Apply
val this : ApplicativeClass<'ApplicativeClass> (requires 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass> and default constructor)
override ApplicativeClass.FMap : f:('T -> 'R) -> fa:Generic<'T,'ApplicativeClass> -> Generic<'R,'ApplicativeClass>
Full name: Script.ApplicativeClass`1.FMap
val f : ('T -> 'R)
val fa : Generic<'T,'ApplicativeClass> (requires 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass> and default constructor)
abstract member ApplicativeClass.Apply : Generic<('T -> 'R),'ApplicativeClass> -> Generic<'T,'ApplicativeClass> -> Generic<'R,'ApplicativeClass>
abstract member ApplicativeClass.Pure : 'T -> Generic<'T,'ApplicativeClass>
Multiple items
type MonadClass<'MonadClass (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)> =
inherit ApplicativeClass<'MonadClass>
new : unit -> MonadClass<'MonadClass>
abstract member Bind : Generic<'T,'MonadClass> * ('T -> Generic<'R,'MonadClass>) -> Generic<'R,'MonadClass>
abstract member Return : 'T -> Generic<'T,'MonadClass>
override Apply : mf:Generic<('T -> 'R),'MonadClass> -> ma:Generic<'T,'MonadClass> -> Generic<'R,'MonadClass>
override Pure : value:'T -> Generic<'T,'MonadClass>
member Then : ma:Generic<'T,'MonadClass> * mb:Generic<'R,'MonadClass> -> Generic<'R,'MonadClass>
Full name: Script.MonadClass<_>
--------------------
new : unit -> MonadClass<'MonadClass>
abstract member MonadClass.Return : 'T -> Generic<'T,'MonadClass>
Full name: Script.MonadClass`1.Return
abstract member MonadClass.Bind : Generic<'T,'MonadClass> * ('T -> Generic<'R,'MonadClass>) -> Generic<'R,'MonadClass>
Full name: Script.MonadClass`1.Bind
val this : MonadClass<'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
member MonadClass.Then : ma:Generic<'T,'MonadClass> * mb:Generic<'R,'MonadClass> -> Generic<'R,'MonadClass>
Full name: Script.MonadClass`1.Then
val ma : Generic<'T,'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
val mb : Generic<'R,'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
abstract member MonadClass.Bind : Generic<'T,'MonadClass> * ('T -> Generic<'R,'MonadClass>) -> Generic<'R,'MonadClass>
override MonadClass.Pure : value:'T -> Generic<'T,'MonadClass>
Full name: Script.MonadClass`1.Pure
val value : 'T
abstract member MonadClass.Return : 'T -> Generic<'T,'MonadClass>
override MonadClass.Apply : mf:Generic<('T -> 'R),'MonadClass> -> ma:Generic<'T,'MonadClass> -> Generic<'R,'MonadClass>
Full name: Script.MonadClass`1.Apply
val mf : Generic<('T -> 'R),'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
val a : 'T
override MonadClass.Pure : value:'T -> Generic<'T,'MonadClass>
type Maybe<'T> =
| None
| Some of 'T
interface Generic<'T,MaybeClass>
Full name: Script.Maybe<_>
union case Maybe.None: Maybe<'T>
union case Maybe.Some: 'T -> Maybe<'T>
Multiple items
type MaybeClass =
inherit MonadClass<MaybeClass>
new : unit -> MaybeClass
override Bind : m:Generic<'T,MaybeClass> * f:('T -> Generic<'R,MaybeClass>) -> Generic<'R,MaybeClass>
override Return : v:'T -> Generic<'T,MaybeClass>
Full name: Script.MaybeClass
--------------------
new : unit -> MaybeClass
val this : MaybeClass
override MaybeClass.Return : v:'T -> Generic<'T,MaybeClass>
Full name: Script.MaybeClass.Return
val v : 'T
override MaybeClass.Bind : m:Generic<'T,MaybeClass> * f:('T -> Generic<'R,MaybeClass>) -> Generic<'R,MaybeClass>
Full name: Script.MaybeClass.Bind
val m : Generic<'T,MaybeClass>
val f : ('T -> Generic<'R,MaybeClass>)
val maybe : MonadClass<MaybeClass>
Full name: Script.maybe
Multiple items
union case ListMonadGeneric.ListMonadGeneric: obj -> ListMonadGeneric<'T>
--------------------
type ListMonadGeneric<'T> =
| ListMonadGeneric of obj
interface Generic<'T,ListMonadClass>
Full name: Script.ListMonadGeneric<_>
Multiple items
type ListMonadClass =
inherit MonadClass<ListMonadClass>
new : unit -> ListMonadClass
override Bind : m:Generic<'T,ListMonadClass> * f:('T -> Generic<'R,ListMonadClass>) -> Generic<'R,ListMonadClass>
override Return : v:'T -> Generic<'T,ListMonadClass>
Full name: Script.ListMonadClass
--------------------
new : unit -> ListMonadClass
val this : ListMonadClass
override ListMonadClass.Return : v:'T -> Generic<'T,ListMonadClass>
Full name: Script.ListMonadClass.Return
override ListMonadClass.Bind : m:Generic<'T,ListMonadClass> * f:('T -> Generic<'R,ListMonadClass>) -> Generic<'R,ListMonadClass>
Full name: Script.ListMonadClass.Bind
val m : Generic<'T,ListMonadClass>
val f : ('T -> Generic<'R,ListMonadClass>)
Multiple items
val list : obj
--------------------
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
module Seq
from Microsoft.FSharp.Collections
val collect : mapping:('T -> #seq<'U>) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.collect
val list' : obj
Multiple items
union case ListAppGeneric.ListAppGeneric: obj -> ListAppGeneric<'T>
--------------------
type ListAppGeneric<'T> =
| ListAppGeneric of obj
interface Generic<'T,ListApplicativeClass>
Full name: Script.ListAppGeneric<_>
Multiple items
type ListApplicativeClass =
inherit ApplicativeClass<ListApplicativeClass>
new : unit -> ListApplicativeClass
override Apply : ff:Generic<('T -> 'R),ListApplicativeClass> -> fa:Generic<'T,ListApplicativeClass> -> Generic<'R,ListApplicativeClass>
override Pure : v:'T -> Generic<'T,ListApplicativeClass>
Full name: Script.ListApplicativeClass
--------------------
new : unit -> ListApplicativeClass
val this : ListApplicativeClass
override ListApplicativeClass.Pure : v:'T -> Generic<'T,ListApplicativeClass>
Full name: Script.ListApplicativeClass.Pure
override ListApplicativeClass.Apply : ff:Generic<('T -> 'R),ListApplicativeClass> -> fa:Generic<'T,ListApplicativeClass> -> Generic<'R,ListApplicativeClass>
Full name: Script.ListApplicativeClass.Apply
val ff : Generic<('T -> 'R),ListApplicativeClass>
val fa : Generic<'T,ListApplicativeClass>
val listf : obj
Multiple items
type AutoOpenAttribute =
inherit Attribute
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
member Path : string
Full name: Microsoft.FSharp.Core.AutoOpenAttribute
--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
val pure : v:'T -> Generic<'T,'ApplicativeClass> (requires 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass> and default constructor)
Full name: Script.ApplicativeModule.pure
val apply : ff:Generic<('T -> 'R),'ApplicativeClass> -> fa:Generic<'T,'ApplicativeClass> -> Generic<'R,'ApplicativeClass> (requires 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass> and default constructor)
Full name: Script.ApplicativeModule.apply
val ff : Generic<('T -> 'R),'ApplicativeClass> (requires 'ApplicativeClass :> ApplicativeClass<'ApplicativeClass> and default constructor)
val ff : Generic<('a -> 'b),'c> (requires 'c :> ApplicativeClass<'c> and default constructor)
val fa : Generic<'a,'c> (requires 'c :> ApplicativeClass<'c> and default constructor)
val f : ('a -> 'b)
val fa : Generic<'a,'b> (requires 'b :> ApplicativeClass<'b> and default constructor)
val fb : Generic<'c,'b> (requires 'b :> ApplicativeClass<'b> and default constructor)
val a : 'a
val b : 'c
Multiple items
val unit : v:'T -> Generic<'T,'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
Full name: Script.MonadModule.unit
--------------------
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
val bind : m:Generic<'T,'MonadClass> -> f:('T -> Generic<'R,'MonadClass>) -> Generic<'R,'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
Full name: Script.MonadModule.bind
val m : Generic<'T,'MonadClass> (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
val f : ('T -> Generic<'R,'MonadClass>) (requires 'MonadClass :> MonadClass<'MonadClass> and default constructor)
val ma : Generic<'a,'b> (requires 'b :> MonadClass<'b> and default constructor)
val mb : Generic<'c,'b> (requires 'b :> MonadClass<'b> and default constructor)
val sequence : list:Generic<'T,'MonadClass> list -> Generic<'T list,'MonadClass> (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
Full name: Script.MonadModule.sequence
Multiple items
val list : Generic<'T,'MonadClass> list (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
--------------------
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val m : Generic<'T,'MonadClass> (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
val ms : Generic<'T,'MonadClass> list (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
val vs : 'T list
val mapM : f:('T -> Generic<'R,'MonadClass>) -> list:'T list -> Generic<'R list,'MonadClass> (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
Full name: Script.MonadModule.mapM
val f : ('T -> Generic<'R,'MonadClass>) (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
Multiple items
val list : 'T list
--------------------
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.map
val filterM : p:('T -> Generic<bool,'MonadClass>) -> list:'T list -> Generic<'T list,'MonadClass> (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
Full name: Script.MonadModule.filterM
val p : ('T -> Generic<bool,'MonadClass>) (requires default constructor and 'MonadClass :> MonadClass<'MonadClass>)
type bool = Boolean
Full name: Microsoft.FSharp.Core.bool
val x : 'T
val xs : 'T list
val b : bool
val ys : 'T list
val k : int
val v : int
val transpose : listoflist:'a -> 'b
Full name: Script.transpose
val listoflist : 'a
val onetoten : ListMonadGeneric<int>
Full name: Script.onetoten
val a : int
val b : int
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
More information