2011年12月4日日曜日

Semigroup, Zero, Monoid

今日はSemigroupでゲソ!

この記事は

Functional Ikamusume Advent Calendar jp 2011

と

一人Scalaz Advent Calendar

を兼ねているんじゃなイカ!?


Semigroup

Semigroupは結合可能という性質を表すでゲソ。

Semigroupは関数 def append(s1: S, s2: => S): S を持ち、2つの値から一つの結果を得る関数を持つでゲソ。

Semigroupのインスタンスはsemigroup関数を使うことで定義できるんじゃなイカ?

Semigroups#semigroup


Semigroupを利用する関数

|+|

加算だけでなく、型によって様々な動きをするでゲソ。


加算や連結、論理和のような動きをするでゲソ。
===と同様に型安全でもあるでゲソ!

・・・・・Semigroup単体だとこれだけでゲソ。

あまりにも寂しいのでZero, Monoidまでやろうじゃなイカ!

Zero

Zeroは単位元を表すでゲソ。

mzero

mzeroは型パラメータを取り、その型の単位元を返すでゲソ。

matchOrZero

matchOrZeroは型パラメータとPartialFunctionを取り、マッチしない場合はその型の単位元を返すでゲソ!


Zeros#zero

Zeroのインスタンスはzeroにより定義できるんじゃなイカ?


そして、SemigroupとZeroを兼ね備えたものがMonoidなのでゲソ!

Monoid

MonoidはSemigroupとZeroを継承したものでゲソ。

Monoidは

forall a. append(zero, a) == a

forall a. append(a, zero) == a

を満たすのでゲソ。


イカ娘も立派なモノイドじゃなイカ?

Monoid単体を利用する関数はほとんどないのでゲソ。
Monoidは他の型クラスと一緒に使うことが多いのでその時に紹介しようじゃなイカ!

Order, Ordering

OrderとOrderingについて。

OrderはEqualを継承しており、比較を可能にします。

Scala標準のAPIにもOrdered, Orderingがありますが、これらはJavaのComparableのように正、零、負で表しています。

しかし、このOrderでは比較結果をOrderingという型で返します。

?|?

比較結果を得るもの。
compareToみたいなもの。


これらがそれぞれequal, less than, greater thanを表しています。

これが素晴らしいところはOrderingがモノイドであること。

これにより、優先順位の高い比較結果から順に結合していくことで適切な比較結果を得られます。


比較結果モノイドについては、 比較はモノイド の記事が面白いので是非見て下さい。

lt, gt, lte, gte

比較する関数です。
標準のものと違うところは型安全なところと、記号じゃないから括弧で括らないといけないところ。


max, min

2値の間で最大、最小を得る関数。


Orders

order, orderBy

Orderのインスタンスを作ります。
orderは2つの値を取り比較結果を返す関数を渡します。
orderByは値を取り、比較可能な値を返す関数を渡します。


scala標準のOrderingも暗黙の型変換でOrderのインスタンスを得ることができます。

比較する際はjava.lang.Comparable, scala.math.Orderingよりもscalaz.Orderの検討を!

2011年12月3日土曜日

Show

今日はShowについて。

Showは表示可能という性質を与えます。

インスタンスは普通にnewで作ることもできますが、Showsに定義された関数を使っていきましょう。

Shows


showは値を受け取り、List[Char]を返す関数を渡します。
文字列ではなく、List[Char]なのはHaskellをリスペクトしてるからでしょうか?
文字列に対してはtoListなどを呼ばないといけません。

それに対してshowsはStringを返す関数を渡せばいいので、こちらを使うことが多いと思います。

showAはShowをtoStringにより実装します。
case classなどはこれでいいかもしれません。

showByは値を取り、Showのインスタンスを持つ型を返す関数を渡します。

基本的にはshowAとshowsを使っていきましょう。

Showを使う関数

show
shows

Showで定義した文字列を取得する関数。
toStringとは違い、表示できることが保証されています(大抵の場合、"A@17d577c"などの文字列は返らない)。


print
println

名前通りの関数。
rpscalaで初めて気がついた。


text

scala.xml.Textを返す関数・・・・・需要あるの?
scala.xml.Elemのインスタンスはデフォルトでは存在しない模様。
こっちの方が重大じゃなイカ。


これらの関数と昨日紹介したassert_===など。
他にもLoggerやWriterに関係するものがあったりするけどまた今度。

2011年12月2日金曜日

Equal

Equalは型クラスです。
型クラスについては10日にやるScala会議で話す資料とか水島さんの死霊とか。

この型クラスは等しいという性質を与えます。

作り方


最初の方法はEqualのインスタンスを直接作るというもの。
二番目の方法はequalを使う方法。
equalは2つの値を受け取り、Booleanを返す述語を渡す。
三番目のequalAはequalをAnyの==を使って実装するというもの。
equalAとequalはEqualsに定義されており、Scalazがそれを継承しています。
この3つはどれも同じEqual[ScalaChan]が作られます。

Eqaulを利用した関数

===
/==

見た目通り等しい、等しくないを返す関数。
標準の==,!=と違うところは型安全というところ。


糖衣関数?もある。


Equalだけを利用した関数が少なすぎて物悲しいのでもう一個

assert_===

Unit TestライブラリによくあるassertEqual的なもの。
エラーメッセージがちょっとかっこいい。
この関数は値がEqualの他にShowのインスタンスを持つことが必要です。


基本的なEqualのインスタンスはEqualのコンパニオンオブジェクトに定義されています。
自分で定義したclassはequalやequalAでインスタンスを作っておきましょう。

Identity

一人Scalaz Advent Calendar

初日ということでIdentityから。

Identityの説明だけれど型クラスに関連するもの(===とか|+|とかほとんどの関数)やScalazのデータ構造(Validation,LazyTupleなど)に関するものは取り扱わないです。
後日EqualやSemigroup,Validationなどを説明するときに出てきます。

Identityは型パラメータAをとり、def value: Aという未定義の関数を持ちます。
パラメータAに様々な関数を提供するコンテナと考えてよいでしょう。


Identitys

IdentitysのmkIdentityによって全ての値はIdentityに暗黙の型変換することができます。
また、unMkIdentityによりIdentityをもとの値に戻すことも可能です。


unitalという謎のIdentity[Unit]が定義されているけど何に利用するかは不明。


Identity

??


簡単に言うとnullチェック。
nullだった場合は引数で与えた値が返る。


|>

関数に呼び出し側の値を適用する関数。
ちょっと意味がわからない、コードを見ましょう。


some, left, right, pair, squared

ある型に包む関数。
pairとsquaredは値のペアをタプルで返す。
def squared = pairみたいな定義だけどいるんですかこれ。


doWhile, whileDo

名前通りの関数。
関数と述語を渡す。


Scalazの型クラス、データ構造に関するものを抜くとこれだけ。

これだけではScalazの便利さがわからないと思うので、ぜひ続きも見て下さい!

2011年9月6日火曜日

ScalazでIteratee その2

前の続き。

実際にファイルを読み込めるようにしました。


EnumeratorMはIterVをモナドで包むための型です。

enumReaderはブログの例とは違いますが、一字ずつ読み込むのではなく、BufferReaderを用いて一行づつ読み込むようにしています。
<<<はScalazで定義されており、composeと同じです。
enumと同様に、Doneになるまで処理を繰り返します。

enumFileはファイルをenumReaderに渡す。
bracketにより、closeReaderが確実に行われることが保証されています。

実行例

現在、scalaz.effectsにあるIterateeな入出力関数はこれらと、標準入力からの読み込みだけです。

2011年9月4日日曜日

ScalazでIteratee

Scala会議でLTしてきました。


拙い発表でしたが、まじめに聞いてくれたScala会議参加者の方々には感謝です。
このLTで話せなかったIterateeについて、tanakhさんのブログを参考に書かせていただきます。

Scalazでの実装

ブログを参考に実際に実装してみます。



定義は簡単。
Haskellのコードとあまり変わりがないですね。(ぇ
ストリームはList(El(1), El(2), El(3), EOF())みたいなイメージです。



enum,runの実装。
enumはfoldl(むしろreduce?)そのままで、IterVを関数と初期値にみたたて、Doneの場合でも結果を返すものと思えばいいです。
runは結果を取り出すだけ。初期値に当たるものがない場合があるので、結果はOptionで返します。



Iterateeたち。
これらをストリームに適用し、結果を得ます。curriedとか初めて使った気がします。
型が消えてしまうので、match式のところはwarningがいっぱいです。
この対処法がないのが残念なところ。(あったら教えてください



モナド。
PartialApplyを使おうとして嵌りました。定義のところで使っちゃダメなんですね・・・・
このインスタンスを作ることで、合成(>>=や>|>)を使うことができます。
Haskellと違って、Monadを定義すればFunctorやApplicativeがついてくるのでちょっと楽。

実行例



Haskellのコードそのままに書けるのは感動ですね。
次はIOを実装しようと思います。