関数モナド

実は、通常の関数もモナドです。 関数モナドは一風変わったモナドです。 それがBindの型にも表れています。 後述のコードからBindの型だけ抜き出すと val (>>=) : m: ('a -> 'b) -> f: ('b -> 'a -> 'c) -> x: 'a -> 'c となるのですが、('a ->)をmとみなすと ('a -> 'b)はm 'b ('b -> 'a -> 'c)は'b -> m 'c ('a -> 'c)はm 'c となっており、全部まとめると m 'b -> ('b -> m 'c) -> m 'c こうなり、いつものBindの型だということがわかります。 (いつもの'aが'b,'bが'cになってますが型変数名は付け替えても同じものです) それではコードを見ていきます。
関数モナド
let (>>=) m f = fun x -> f (m x) x 
let join m = m >>= id
type FuncBuilder() =
    member __.Bind (m,f) = m >>= f
    member __.Return x = fun _ -> x
let func = FuncBuilder()

let test1 = func{
    let! a = ((+)1) //11
    let! b = ((*)2) //20
    return (a+b)    //31
    }

let test2 = func{
    let! a = Some // a=Some [10]
    return a
    }
let test3 = func{
    let! a = Array.length           //3
    let! b = Array.length >> ((+)1) //4
    return (a+b)
    }
let test4 = func{
    let! a = join (+) //10+10 = 20
    let! b = join (*) //10*10 = 100
    return a + b      //120
    }
printfn "%A" <| test1 10
printfn "%A" <| test2 [10]
printfn "%A" <| test3 [|10;20;30|]
printfn "%A" <| test4 10
Bindの実装は短いですがちょっと難しいです。 丸覚えしてしまうのが良いかもしれません。 testでは、様々な1引数関数をlet!で受け取っています。 本家のhaskellでは、モナドを操作する関数が色々あるので 関数モナドはここで示した以上に便利なものです。 その一例としてjoin関数を定義して使ってみました。 returnとjoinがあればreturnとBindを使わなくても実はモナドが定義できます。 (>>=) m f = join (fmap f m)とBindが定義できるからです。 (ただしfmapが必要になります) 関数モナドにjoinを適用すると、二引数関数に同じ引数を2回渡して 1引数関数にするという動作になります。面白いですよね。 joinの型はm (m a) -> m aであり 関数モナドの場合は(a -> a -> b) -> a -> bとなります。