Codensityについてググると、
The Mother of all Monads
という記事が見つかる。
Codensityは継続モナドとほぼ同じものみたい。
この記事にある例をScalaで書いてみる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def i[F[+_]: Monad, A](a: F[A]) = new Codensity[F, A] { | |
def apply[B](f: A => F[B]) = a >>= f | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val map = Map('foo -> "bar", 'hoge -> "fuga") | |
(for { | |
x <- i(map get 'foo) | |
y <- i(map get 'hoge) | |
} yield x + y).improve assert_=== Some("barfuga") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type StrDisj[+A] = String \/ A | |
(for { | |
x <- i[StrDisj, String]((map get 'foo) \/> "foo") | |
y <- i[StrDisj, String]((map get 'baz) \/> "baz") | |
} yield x + y).improve assert_=== "baz".left |
CodensityがOptionやDisjunctionとして動く。
でもこれってIdTじゃ(ry
Codensityは継続モナドのようなもの、ということで継続らしい例を書いてみる。
iprintで、計算の経過を表示する。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def iprint[F[+_]: Monad, A](a: F[A]) = new Codensity[F, A] { | |
def apply[B](f: A => F[B]) = { | |
println(a) | |
a >>= f | |
} | |
} | |
(for { | |
x <- iprint(map get 'foo) | |
y <- iprint(map get 'baz) | |
} yield x + y).improve assert_=== None |
継続を破棄するbreakを定義し、for式で使ってみる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def break[F[+_]: PlusEmpty, A] = new Codensity[F, A] { | |
def apply[B](f: A => F[B]) = PlusEmpty[F].empty[B] | |
} | |
(for { | |
x <- iprint(map get 'foo) | |
_ <- break[Option, String] | |
y <- iprint(map get 'hoge) | |
} yield x + y).improve assert_=== None |
無事、計算が破棄された。
Codensityはあるモナドにおいて計算量を減らせることがわかった。
他にも何か出来そうだが、わたしが思いついたのはこれくらい。
0 件のコメント:
コメントを投稿