Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Last active June 24, 2021 01:09
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/6574b69abd5ed47a6743 to your computer and use it in GitHub Desktop.
Save xuwei-k/6574b69abd5ed47a6743 to your computer and use it in GitHub Desktop.
Scalaz-Streamの基本的なクラスや概念まとめ

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

  • versionは0.7a

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

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

scalaz-stream内のclass

  • 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, α] })#λ]
  • 純粋なメモリ上のシーケンスの表現?
  • Process0 に限らないが、Nothingをあてはめたり、varianceを使ったり、良くも悪くもすべてをProcessとそのtype aliasで表現することにより、わかりずらさの一因になってる気はする
  • FTaskIO, I は入力, O は出力
  • Process1 とは違い、大抵副作用があるものの表現につかう?
  • この言い方で適切なのか、ちょっと自信ない
  • というか、F[_]Taskが入ることにより、 ChannelChannel を走らせた Task 自体は純粋なデータ構造で、最後に Task を走らせる際に副作用があるので、そこを勘違いしないように
  • 標準で用意されている、 Channel を返すメソッド例
  • def chunkR(is: => InputStream): Channel[Task,Int,ByteVector] 元のInputStreamからのbyte数を引数にとり、受け取ったByte数毎にわけて出力が取得できる、というもの
  • 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 あとで書く
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment