Skip to content

Instantly share code, notes, and snippets.

@serjKim
Last active April 14, 2020 12:20
Show Gist options
  • Select an option

  • Save serjKim/55a8f3881fd6200a99378ae8286645cf to your computer and use it in GitHub Desktop.

Select an option

Save serjKim/55a8f3881fd6200a99378ae8286645cf to your computer and use it in GitHub Desktop.
F#: Functor, Applicative, Monad
type F<'a> = F of 'a

module Functor =
    // Def
    // map : f:('a -> 'b) -> F<'a> -> F<'b>
    let map f (F x) = F (f x)

    let x = F 123
   
    // Laws
    // 1. map id x = x
    printfn "equal %b" (map id x = x)
    // 2. (map f x) o (map g x) = map (f o g) x
    let f x = x + 100
    let g x = x - 1
    let fg = map f >> map g
    let h = map (f >> g)
    printfn "equal %b" (fg x = h x)

module Applicative =
    open Functor

    // Def
    // apply : F<('a -> 'b)> -> F<'a> -> F<'b>
    let apply (F f) (F x) = F (f x)
    // return : x:'a -> F<'a>
    let ``return`` x = F x

    let x = F 123

    // Laws
    // 1. map f x = apply (return f) x
    let f x = x + 100
    printfn "equal %b" (map f x = apply (``return`` f) x)

module Monad =
    open Functor
    open Applicative

    // Def
    // bind : f:('a -> F<'b>) -> F<'a> -> F<'b>
    let bind (f: 'a -> F<'b>) (F x) = f x

    let mx = F 123

    // Laws
    // 1. bind f (return x) = f x
    let f x = F (x + 100)
    printfn "equal %b" (bind f (``return`` 123) = f 123)
    // 2. bind return x = x 
    printfn "equal %b" (bind ``return`` mx = mx)
    // 3. mx.bind(x -> f(x).bind(g)) = mx.bind(f).bind(g)
    //    or
    //    bind (x -> bind g (f x)) mx = bind g (bind f mx)
    let g x = F(x - 1)
    let p1 = bind g (bind f mx)
    let p2 = bind (fun x -> bind g (f x)) mx
    printfn "equal %b" (p1 = p2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment