2011年12月6日火曜日

Pure

Scalazはモナモナしたデータ構造が多いので早くMonadところまでやりたい・・・

ということで今日はPureを書きます。

Pure

Pureは"型パラメータを1つとる型"を型パラメータにとり、値を包み込む関数を持ちます。

分かりにくいので例を挙げます。

case class ScalaChan[A](value: A)
implicit def ScalaChanEqual[A]: Equal[ScalaChan[A]] = equalA
implicit def ScalaChanShow[A]: Show[ScalaChan[A]] = showA
implicit def ScalaChanPure = new Pure[ScalaChan] {
def pure[A](a: => A) = ScalaChan(a)
}
"Scalaちゃん".pure[ScalaChan] assert_=== ScalaChan("Scalaちゃん")
view raw pure1.scala hosted with ❤ by GitHub

Pureを利用した関数では、計算をして結果を包むものが多いです。

pure

型を渡し、値をその型で包みます。

1.pure[List] assert_=== List(1)
"Scalaz".pure[Option] assert_=== "Scalaz".some
'Scalaz.pure[Function0] assert_=== (() => 'Scalaz)
view raw pure2.scala hosted with ❤ by GitHub

iterate, repeat, replicate

iterate, repeatは無限リストなんかを作る関数。
Stream以外に使えるものはあるのだろうか?

replicateはiterate, repeatと似ているけれど、大きさが決まっています。
これはListなどでも使えます。

1.iterate[Stream](1 +).take(3) assert_=== Stream(1, 2, 3)
1.repeat[Stream].take(3) assert_=== Stream(1, 1, 1)
1.replicate[List](3) assert_=== List(1, 1, 1)
lazy val nextPrime: Int => Int = _.doWhile(1 +, i => (2 until i).any(i % _ == 0))
2.iterate[Stream](nextPrime).take(5) assert_=== Stream(2, 3, 5, 7, 11)
2.replicate[List](5, nextPrime) assert_=== List(2, 3, 5, 7, 11)
2.replicate[Option](3) assert_=== 6.some
view raw pure3.scala hosted with ❤ by GitHub

+>:

値を包み込み、結合する演算子。
使い方がよくわからず、 List(1).+>:(1) とか書いてたけど : がついてるとレシーバが右にくるとの御指摘が。
演算子の結合順位もよくわかっていないのでコップ本を読み直さないとですね・・・

1 +>: List(1) assert_=== List(1, 1)
1 +>: 1.some assert_=== 2.some
(1 +>: ((_: Int) + 1)).apply(1) assert_=== 3
view raw pure4.scala hosted with ❤ by GitHub

MA

今回の関数は +>: 以外Identityに定義されています。
+>: はどこに定義されているのかというと、MAに定義されています。

MAは"型パラメータを1つとる型"Mと型Aを型パラメータにとります。

scala> (nil[Int]: MA[List, Int])
res65: scalaz.MA[List,Int] = scalaz.MAs$$anon$3@1d45221
scala> (none[String]: MA[Option, String])
res66: scalaz.MA[Option,String] = scalaz.MAsLow$$anon$1@90cae4
view raw ma.scala hosted with ❤ by GitHub

Scalaではイレイジャで型M[A]の型Aが消えてしまうため、このような定義になっています。

このMAでは、"型パラメータを1つとる型"を対象にした型クラスを利用する関数が定義されています。

今後紹介する関数では、Identity,MAそしてMABで定義されたものを中心に紹介していきます。

これらはScalaz特有の関数を利用するための型クラスなので深い理解はいりませんが、Scalazを使う上で覚えておいて損はないでしょう。

1 件のコメント: