6 people like it.
Like the snippet!
Simple typeclass implementation
I learned how to implement this by reading this great good project http://code.google.com/p/fsharp-typeclasses/
But I can't understand why the project needs ternary operator.
I used binary operator and seems it's okay.
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:
|
type Return() =
static member (?) (_:Return, _:'a option) = fun (x:'a) -> Some x
static member (?) (_:Return, _:'a list) = fun (x:'a) -> [x]
let inline return' x : ^R = Return() ? (Unchecked.defaultof< ^R>) x
type Bind() =
static member (?) (_:Bind, m:option<_>) = fun f -> Option.bind f m
static member (?) (_:Bind, m:list<_> ) = fun f -> List.collect f m
let inline (>>=) m f : ^R = Bind() ? (m) f
type DoNotationBuilder() =
member inline b.Return(x) = return' x
member inline b.Bind(p,rest) = p >>= rest
let do' = new DoNotationBuilder()
[4;5;6] >>= (fun x -> [x;x*10]) |> printfn "%A"
// [4; 40; 5; 50; 6; 60]
Some 7 >>= (fun x -> List.tryFind((=)x) [7;8;9]) |> printfn "%A"
// Some 7
do' {
let! greeting = ["Good morning";"Good evening"]
let! name = ["Alice";"Bob"]
return printfn "%s, %s." greeting name
}
// Good morning, Alice.
// Good morning, Bob.
// Good evening, Alice.
// Good evening, Bob.
do' {
let! id = Some "Carol123"
let! password = Some "*****"
return printfn "Hi, %s" id
}
// Hi, Carol123
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
|
type Fmap() =
static member (?) (_:Fmap , m:_ option) = fun f -> Option.map f m
static member (?) (_:Fmap , m:_ list) = fun f -> List.map f m
let inline (<%>) f x = Fmap() ? (x) f
type Ap() =
static member (?) (_:Ap , mf:_ option) = fun (m:_ option) ->
match mf , m with Some f , Some x -> Some (f x) | _ -> None
static member (?) (_:Ap , mf:_ list) = fun (m:_ list) ->
[ for f in mf do for x in m -> f x]
let inline (<*>) mf m = Ap() ? (mf) m
(+) <%> ["a";"b"] <*> ["x";"y";"z"] |> printfn "%A"
// ["ax"; "ay"; "az"; "bx"; "by"; "bz"]
(fun a b c -> a + b + c) <%> [100;200] <*> [10;20] <*> [1;2] |> printfn "%A"
// [111; 112; 121; 122; 211; 212; 221; 222]
printf "%s, %s" <%> Some "hello" <*> Some "applicative" |> printfn "%A"
// hello, applicative
|
Multiple items
type Return =
new : unit -> Return
static member ( ? ) : Return * 'a option -> ('a -> 'a option)
static member ( ? ) : Return * 'a list -> ('a -> 'a list)
Full name: Script.Return
--------------------
new : unit -> Return
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
val x : 'a
union case Option.Some: Value: 'T -> Option<'T>
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val return' : x:'a -> 'R (requires member ( ? ))
Full name: Script.return'
module Unchecked
from Microsoft.FSharp.Core.Operators
val defaultof<'T> : 'T
Full name: Microsoft.FSharp.Core.Operators.Unchecked.defaultof
Multiple items
type Bind =
new : unit -> Bind
static member ( ? ) : Bind * m:'c option -> (('c -> 'd option) -> 'd option)
static member ( ? ) : Bind * m:'a list -> (('a -> 'b list) -> 'b list)
Full name: Script.Bind
--------------------
new : unit -> Bind
val m : 'c option
val f : ('c -> 'd option)
module Option
from Microsoft.FSharp.Core
val bind : binder:('T -> 'U option) -> option:'T option -> 'U option
Full name: Microsoft.FSharp.Core.Option.bind
val m : 'a list
val f : ('a -> 'b 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 collect : mapping:('T -> 'U list) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.collect
val m : 'a (requires member ( ? ))
val f : 'b
Multiple items
type DoNotationBuilder =
new : unit -> DoNotationBuilder
member Bind : p:'a * rest:'b -> 'c (requires member ( ? ))
member Return : x:'d -> 'e (requires member ( ? ))
Full name: Script.DoNotationBuilder
--------------------
new : unit -> DoNotationBuilder
val b : DoNotationBuilder
Multiple items
member DoNotationBuilder.Return : x:'d -> 'e (requires member ( ? ))
Full name: Script.DoNotationBuilder.Return
--------------------
type Return =
new : unit -> Return
static member ( ? ) : Return * 'a option -> ('a -> 'a option)
static member ( ? ) : Return * 'a list -> ('a -> 'a list)
Full name: Script.Return
--------------------
new : unit -> Return
val x : 'd
Multiple items
member DoNotationBuilder.Bind : p:'a * rest:'b -> 'c (requires member ( ? ))
Full name: Script.DoNotationBuilder.Bind
--------------------
type Bind =
new : unit -> Bind
static member ( ? ) : Bind * m:'c option -> (('c -> 'd option) -> 'd option)
static member ( ? ) : Bind * m:'a list -> (('a -> 'b list) -> 'b list)
Full name: Script.Bind
--------------------
new : unit -> Bind
val p : 'a (requires member ( ? ))
val rest : 'b
val do' : DoNotationBuilder
Full name: Script.do'
val x : int
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val tryFind : predicate:('T -> bool) -> list:'T list -> 'T option
Full name: Microsoft.FSharp.Collections.List.tryFind
val greeting : string
val name : string
val id : string
val password : string
Multiple items
type Fmap =
new : unit -> Fmap
static member ( ? ) : Fmap * m:'c option -> (('c -> 'd) -> 'd option)
static member ( ? ) : Fmap * m:'a list -> (('a -> 'b) -> 'b list)
Full name: Script.Fmap
--------------------
new : unit -> Fmap
val f : ('c -> 'd)
val map : mapping:('T -> 'U) -> option:'T option -> 'U option
Full name: Microsoft.FSharp.Core.Option.map
val f : ('a -> 'b)
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.map
val f : 'a
val x : 'b (requires member ( ? ))
Multiple items
type Ap =
new : unit -> Ap
static member ( ? ) : Ap * mf:('c -> 'd) option -> ('c option -> 'd option)
static member ( ? ) : Ap * mf:('a -> 'b) list -> ('a list -> 'b list)
Full name: Script.Ap
--------------------
new : unit -> Ap
val mf : ('c -> 'd) option
val x : 'c
union case Option.None: Option<'T>
val mf : ('a -> 'b) list
val mf : 'a (requires member ( ? ))
val m : 'b
val a : int
val b : int
val c : int
val printf : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
More information