Wintus
4/24/2015 - 6:06 PM

Scalaz-Streamの基本的なクラスや概念まとめ

Scalaz-Streamの基本的なクラスや概念まとめ

Scalaz-Streamの基本的なクラスや概念まとめ

  • versionは0.7a

scalaz-streamが依存してるライブラリ内のclass

scalaz.concurrent.Future

  • scalaz-streamではなくscalaz-concurrentにあるクラス
  • scalaz-streamは、これと Task にかなり依存してるので、まずはこれらを理解することが重要
  • Scala標準Futureと違い
  • 走っている状態 は存在しない。純粋なデータ構造である
  • エラー処理は行わない。別スレッドで走らせた際に例外発生したら、永遠にブロックする。つまり、実質Taskとして使うことがほとんどで、Futureを直接使うことはない
  • 例の本 Scala関数型デザイン&プログラミング ―Scalazコントリビューターによる関数型徹底ガイド の7章で説明している Par と基本的には同じものなので、それを読むとよい
  • 内部の低レベルな部分は java.util.concurrentConcurrentLinkedQueue, CountDownLatch, AtomicInteger, AtomicBoolean, AtomicReferencescala.concurrent.SyncVar などを使って実装されている

scalaz.concurrent.Task

  • class Task[+A](val get: Future[Throwable \/ A]) というもの。FutureはScala標準のものではなく、ScalazのFuture
  • これも同じくscalaz-streamのクラスではなくscalaz-concurrentのクラス

scodec.bits.ByteVector

scalaz-stream内のclass

Process[F[+_], +O]

  • scalaz-stream内で、一番最重要で基礎となるクラス
  • コレクションのように扱え、0個以上のO (2つめの型パラメータ)のシーケンスと捉えることも可能だが、実態は状態マシンである
  • 事実、コレクションにあるようなメソッドの大半がProcessにもある
  • F[_]O に当てはめる型パラメータの種類によって、入力元も出力先も表す
  • つまり、IterateeにおけるEnumeratorやEnumerateeなどに相当するものも、全部 Process で表現する
  • 例の本 Scala関数型デザイン&プログラミング ―Scalazコントリビューターによる関数型徹底ガイド の15章で解説されているものは、ある意味これ
  • ただし、本のほうは、Stackoverflow回避のためのトランポリンがされていなかったり、もう少し単純
  • Process1, Process0, Tee, Wye などとして使う場合を除けば F[_] には大抵の場合 Task が入るはず。もしくは IO
  • なぜかというと、 F[_]scalaz.Catchable を要求するメソッドがあり、 scalaz.Catchable のインスタンスはかなり限られているため
  • 無条件でMonadPlus
  • MonadPlus[({ type λ[α] = Process[F, α] })#λ]

type Process0[+O] = Process[Nothing,O]

  • 純粋なメモリ上のシーケンスの表現?
  • Process0 に限らないが、Nothingをあてはめたり、varianceを使ったり、良くも悪くもすべてをProcessとそのtype aliasで表現することにより、わかりずらさの一因になってる気はする

type Process1[-I,+O] = Process[Env[I,Any]#Is, O]

type Sink[+F[_],-O] = Process[F, O => F[Unit]]

type Channel[+F[_],-I,O] = Process[F, I => F[O]]

  • FTaskIO, I は入力, O は出力
  • Process1 とは違い、大抵副作用があるものの表現につかう?
  • この言い方で適切なのか、ちょっと自信ない
  • というか、F[_]Taskが入ることにより、 ChannelChannel を走らせた Task 自体は純粋なデータ構造で、最後に Task を走らせる際に副作用があるので、そこを勘違いしないように
  • 標準で用意されている、 Channel を返すメソッド例
  • def chunkR(is: => InputStream): Channel[Task,Int,ByteVector] 元のInputStreamからのbyte数を引数にとり、受け取ったByte数毎にわけて出力が取得できる、というもの

type Tee[-I,-I2,+O] = Process[Env[I,I2]#T, O]

  • 2つの入力を合成して、1つにすることを表現する関数というか状態マシン
  • 標準で用意されている Tee を返すメソッド例
  • def zipWith[I, I2, O](f: (I, I2) => O): Tee[I, I2, O] 純粋な関数からTee生成

Wye

  • TODO あとで書く

Writer

  • TODO あとで書く

Queue

  • TODO あとで書く

Topic

  • TODO あとで書く

WriterTopic

  • TODO あとで書く

Signal

  • TODO あとで書く