今日はMonad。
Monad
Monadが何たるかは
モナドは象だ
を読みましょう!(まるなげ
モナドなんて高階関数を持ってて結合可能なコンテナぐらいの認識でいいのです!(ぼうろん
ここではScalazでMonadに関連する関数を紹介します。
Monadのインスタンスを直接定義するか、BindとPureのインスタンスが定義されていればimplicit parameterにMonadのインスタンスが供給されます。
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
case class ScalaChan[A](value: A) | |
implicit def ScalaChanEqual[A]: Equal[ScalaChan[A]] = equalA | |
implicit def ScalaChanShow[A]: Show[ScalaChan[A]] = showA | |
implicit lazy val ScalaChanPure: Pure[ScalaChan] = new Pure[ScalaChan] { | |
def pure[A](a: => A): ScalaChan[A] = ScalaChan(a) | |
} | |
implicit lazy val ScalaChanBind: Bind[ScalaChan] = new Bind[ScalaChan] { | |
def bind[A, B](a: ScalaChan[A], f: A => ScalaChan[B]): ScalaChan[B] = f(a.value) | |
} | |
def f[A[_]: Monad, B: Semigroup](a: A[B]) = for { | |
i <- a | |
j <- a | |
} yield i |+| j | |
f(100.some) assert_=== 200.some | |
f(ScalaChan("Scala")) assert_=== ScalaChan("ScalaScala") | |
implicit lazy val ScalaChanMonad: Monad[ScalaChan] = new Monad[ScalaChan] { | |
def pure[A](a: => A): ScalaChan[A] = ScalaChan(a) | |
def bind[A, B](a: ScalaChan[A], f: A => ScalaChan[B]): ScalaChan[B] = f(a.value) | |
} |
getOrElseM
値Mに包まれたOption[A]がSomeの場合、値を返し、Noneの場合呼び出し側を返します。
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
'Scalaz.wrapNel.getOrElseM('Scala.some.wrapNel) assert_=== NonEmptyList('Scala) | |
'Scalaz.wrapNel.getOrElseM(none.wrapNel) assert_=== NonEmptyList('Scalaz) |
ifM
trueの場合とfalseの場合で値を振り分けます。
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
true.some.ifM('Scalaz.some, 'Scala.some) assert_=== Option('Scalaz) | |
nel(false, true, false).ifM('イカちゃん.wrapNel, 'Scalaちゃん.wrapNel) assert_=== NonEmptyList('Scalaちゃん,'イカちゃん,'Scalaちゃん) |
replicateM
型パラメータを1つとる型と繰り返す回数を渡し、包まれた値を連結します。
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
'Z'.some.replicate[List](5) assert_=== List(Option('Z'), Option('Z'), Option('Z'), Option('Z'), Option('Z')) | |
'Z'.some.replicateM[List](3) assert_=== Option(List('Z', 'Z', 'Z')) |
foldLeftM, foldRightM
普通のfoldと違い、包まれた値を返す関数を渡します。
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
nel(1, 2, 3).foldLeftM(mzero[Int])(_ |+| _ |> (i => (i % 2 === 0).option(i))) | |
nel(1, 2, 3).foldLeftM(mzero[Int])(_.replicate[List](_)) assert_=== List(0, 0, 0, 0, 0, 0) |
Scalaではあるクラスを実装するのではなく、flatMapとmapさえ実装されていればfor式が使えちゃう。
for式はflatMapがネストしたら使えばいいんじゃなイカ?
0 件のコメント:
コメントを投稿