decadence

個人のメモ帳

独習Scalazを読むだけ

独習 Scalaz — 独習 Scalaz 気がついたらある程度読めるようになっていた

scalaz/exampleってディレクトリあったの知らなかった
例えばStateTUsage.scalaではフィボナッチ数列生成をStateモナド使ってやってる例がある

型クラスとかデータ構造とか

  • Semigroup : 二項演算で結合則 (scalazなら|+|が二項演算)
  • Monoid: Semigroup + 単位元(zero)
    • 単位元の左右どちらにappendしても同じ値
  • Functor -> fmap (map)
    • F map id == F で元に戻る
    • 関数f,gについて、F.map(f.compose(g)) == F.map(g).map(f)
    • ScalazではFunctorLaw+scalacheck-bindingでテスト出来る
  • Applicative -> pure, ap<*>
    • ..
  • Foldable[F[_]] -> foldMap/foldRight
  • Bind -> bind>>= (flatMap)
  • (Scalazでは) Monad[F[_]] extends Applicative[F] with Bind[F]
  • MonadPlus[F[_]] exnteds Monad[F] with ApplicativePlus[F] -> filter(単位元と畳み込み)
  • Scalazでは Plus[F[_]](≒ Semigroup[A])とPlusEmpty[F[_]](≒ Monoid[A])みたいのがある
  • Writer: run, written, value (3.set(Vector("log")), Vector("log").tell etc...)
    • Writer[+W, +A] は、WriterT[Id, W, A] の型エイリアス
    • 値を計算しながらログを残すとか
  • Readerモナド <=> 関数モナド (全ての関数が共通の情報を読む)
  • Stateモナドは関数のラッピングに特化f: S => (S, A)
    • type State[S, +A] = StateT[Id, S, A]
    • forで個々の演算をStateを引き回さずに連鎖出来る
    • TODO ねこはるさんのScalazでTetrisみたいのがこんなんだった
  • Eitherモナド\/: 失敗の文脈を与えるモナド
  • Validation <- validation/disjuction -> \/
    • Validationはモナドではなく、Applicative functor
    • 最初のイベントの結果を次へと連鎖するのではなく、全イベントを検証する(Formとかetc)
  • NonEmptyListNEL: ValidationNELにおけるFailure中身はNEL
  • Kleisli: A => M[B]という型の関数に対する特殊なラッパー
    • >=>: alias for andThen
    • <=<: alias for compose
    • case class Kleisli[M[_], A, B](run: A => M[B])
    • ReaderはKleisliの特殊系 -> MがIdとなる
  • Zipper: Stream向けのものを提供
    • あるデータ構造の注目点、および周辺の情報を含んでいるデータ構造は Zipper と呼ばれます
  • Id: HaskellControl.Monad.Identity
    • 全てのデータ型はその型のIdとなれる (0: Id[Int])
    • 下の方にあるReaderとKleisliの例とか
    • |>に関数を渡したり、visitにPartialFunction渡したり
  • Length, Index, Each等の無法者の型クラス
    • 型クラスっちゃ型クラスだけど、そんなに有用でないとかそんなん
  • モナド変換子: ref Read World Haskell
    • Readerのモナド変換子版がReaderT: type ReaderT[F[_], E, A] = Kleisli[F, E, A]
    • State [a] (Maybe a) <=> StateT [a] Maybe a
    • モナド変換子はモナドを含む型引数を持つものを特別扱いしてる感じかな
    • 下の方でStateTReaderTOptionの例を軽く読んでる
  • Lens: 入れ子になったデータ構造を不変なまま更新する需要
    • case classのcopy...copyとかのやつ
    • LensはStore(setter/geterのラッパー)を使う
    • Lens.lensu[A, B]: Aがオブジェクトで、BがAに含まれる更新されるやつの型
    • 確かにStateモナドかっていわれたら近い
    • LensLawのdoubleSet (2度setしてgetすると2度目にsetしたものが得られる)、なんで最新のものが得られる的な感じじゃないんだろう
  • DList: difference list (名前HListっぽいな? )
    • 定数時間での追加をサポートするデータ構造
  • Idiomatic traversal: Traverse
    • List[A], f: A => Option[A] から Option[List[A]]みたいなの作れるやつ、最高
    • trait Traverse[F[_]] extends Functor[F] with Foldable[F]
    • final def traverse[G[_], B](f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = G.traverse(self)(f)
    • Applicativeなインスタンスを持つ型を生成するやつに利用出来るって感じ
  • Traverseのsequence?
    • haskell sequence :: Monad m => [m a] -> m [a] <- なるほど〜
    • List(1.some, 2.some).sequence => Some(List(1,2))
    • List(1.some, none).sequence => None
    • ValidationとTreeの例とか便利過ぎる
  • Arrow <=> Function1[A, B], PartialFunction[A, B], Kleisli[F[_], A, B], CoKleisli[F[_], A, B]
    • ScalaにはFunctionNとかあるけど、ScalazにはArrowが別にある
      • trait Arrow[=>:[_, _]] extends Split[=>:] with Profunctor[=>:] with Category[=>:] { self => ...
      • trait Category[=>:[_, _]] extends Compose[=>:] { self =>...
      • A scalaz.Category supporting all ordinary functions, as well as combining arrows product-wise.
      • うーん、ArrowがCategoryをmixinする?射に圏がmixinされてるって読んでいいのかな
      • 射=Functorではなく...?Arrowはそのへんの抽象化らしい
    • idが恒等射、arrは関数から射を作り、firstは既存の射からペアを取ってペアを返す射を作る
    • ***は2つの射を両方共同じ値に対して実行する事で新しい射を提供する
    • &&&は同じ値を2つの射に実行してペアを返すような射を作る
  • Compose[=>:]: 2つの射を合成するcompose>>><<<などを提供
    • Composeは型引数1つで、Categoryは型引数を2つ取る型引数を1つ取る高カインド型で、取った1つの型引数(=>:)をそのままComposeに渡してるって感じ
      • 幸いなことに自然と=>:が単なる1つの型引数ってのが読めるようになってた(って説明も後ろにあった)
      • trait Foo[F[_,_]] { def foo[A]: A F A }
  • Unapply: 異なるカインド付けされた型の間での型推論のためのもの
    • Applicative[M[_]] <=> Unapply[Applicative, X]
  • Memo: メモ化
    • sealed trait Memo[@specialized(Int) K, @specialized(Int, Long, Double) V]
    • まてまて、@specialized知らんぞ...scala標準のアノテーション...ほー
      • scala.specializedアノテーションは、Javaのプリミティブ型を使うよう指示するアノテーション LINK
    • Memo.mutableHashMapMemo使うだけかんたん
  • ST: Stateっぽい?
    • Purely functional mutable state threads.
    • "Lazy Functional State Threads"って論文
    • 状態が可変で上書きされるけど、外から観測出来ないらしい
  • STRefはSTモナドの中でしか使えない可変変数を表すデータ構造
  • STArrayとかもあって、可変配列に対する処理を外から見えない形で処理出来る
  • IO
    • これはSTの状態をRealWorldってのに固定したものっぽい
    • 最近じゃ、World[RealWorld]ってのがTower[IvoryTower]ってのに変わってる、IvoryTowerってのを後で調べてみる
    • haskellにあるIOモナドとだいたい同じっぽい
  • Iteratee
    • Input, Step, Enumerator, EnumerateeとかあるしPlayのと用途は同じっぽい
    • データが連なって来るのを順に処理するって感じ
    • Iteratee[E,A]EInput[E]になってAが計算結果の方
    • IterateeT[E, F[_], A]ってのもあって、結果をFで囲む事もできるし、Idを使えばそのままの値が得られる
    • IterateeTを使えば入力処理等も行える: Iteratee.enumReader[F[_]](r: => java.io.Reader)
  • Free: mapしか定義されてないモナド(下の方でもFreeのbindについて見てる)
    • Scalazでは、FreeコンストラクタFree.Suspend、(Haskellでいう)PureをFree.Returnと定義する
    • それとFreeを返す関数を処理するFree.Gosubもある
    • Functorのリストって考え方が一番分かりやすいかも <- これかな....
      • Functorの処理内容を中に中にどんどん含めてく感じ
    • Freeのbind(flatMap)は以下のように定義される
sealed abstract class Free[S[_], A] {
  final def flatMap[B](f: A => Free[S, B]): Free[S, B] = this match {
    case a @ Gosub() => gosub(a.a)(x => gosub(() => a.f(x))(f))
    case a           => gosub(() => a)(f)
  }
sealed abstract class FreeInstances extends FreeInstances0 with TrampolineInstances with SinkInstances with SourceInstances {
  implicit def freeMonad[S[_]:Functor]: Monad[({type f[x] = Free[S, x]})#f] =
    new Monad[({type f[x] = Free[S, x]})#f] {
      def point[A](a: => A) = Return(a)
      override def map[A, B](fa: Free[S, A])(f: A => B) = fa map f
      def bind[A, B](a: Free[S, A])(f: A => Free[S, B]) = a flatMap f
    }
}
  • Trampoline: Function0のFreeモナド
    • 実装簡単で分かりやすい
    • Stackless nanntara <- これもねこはるさんかだれかの何かあった気がする

なんか

  • scala repl :k -v Option
  • コンストラクタ = 1階カインド型 = プロパーな型になるのに他の型を受け取る型
  • 高カインド型 = X[F[A]] = eg ( -> ) -> * = 型コンストラクタを受け取る型コンストラクタ
  • FunctorはX[F[A]]なのに、List(F[+A])がfunctorなのはなんで?
  • HaskellnewtypeがTaggedType(@@)
    • wrapした値クラスとかに.valueみたいの呼ばなくて済むのが便利みたいな使い方
    • A @@ KilogramはKilogramってTag付けされたtypeを持つA型のクラス -> A with Tag[Kilogram]
    • Double with Tag[Kilogram]とかにすると上で挙げた使い方になる
    • 直接値を渡したりするとコンパイルエラー -> ただのtypeとは違う
  • Disjunction/Conjunction <-> 論理和/論理積
    • Tagもある
  • Option[A]は、AがSemigroupである場合にMonoidになれる
  • for { x <- 1 |-> 40 if x...} yield xって書ける
  • モナディックな関数群
    • join[B](implicit ev: A <~< F[B]): F[B](flatten)
    • filterM[M[_] : Monad](p: A => M[Boolean]): M[List[A]]
    • foldLeftM[G[_], A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit M: Monad[G]): G[B]
  • ReaderはKleisliの特殊系とは?多分こんな感じ
val addStufR: Reader[Int, Int] = for {
  a <- Reader{(_: Int)*2}
  b <- Reader{(_: Int)+10}
} yield a + b
addStafR(3) // -> 19
// Idを使った場合と等価
val addStufK: Kleisli[Id, Int, Int] = for {
  a <- Kleisli{(x: Int) => (x*2: Id[Int])}
  b <- Kleisli{(x: Int) => (x+10: Id[Int])}
} yield a+ b
addStafR(3) // -> 19
  • Tree: Scalazでは多分木
    • TreeのためのZipperはScalazのTreeLoc
  • Zipperが何を表現するのか
scala> Stream(1, 2, 3, 4).toZipper >>= {_.next}
res25: Option[scalaz.Zipper[Int]] = Some(Zipper(<lefts>, 2, <rights>))
  • 10日目モナド変換子...このへんから難しいとこ
  • Readerのモナド変換子版であるReaderTをOptionの上に積む
    • ReaderTOption:(そもそもtype ReaderT[F[_], E, A] = Kleisli[F, E, A]
type ReaderTOption[A, B] = ReaderT[Option, A, B]
object ReaderTOption extends KleisliInstances with KleisliFunctions {
  def apply[A, B](f: A => Option[B]): ReaderTOption[A, B] = kleisli(f)
}
  • この例何のためにKleisli使うのかとか分かりやすくて良いな (エラー情報消えるからValidationの方が良いけど)
scala> def configure(key: String) = ReaderTOption[Map[String, String], String] {_.get(key)}
configure: (key: String)ReaderTOption[Map[String,String],String]
scala> def setupConnection = for {
         host <- configure("host")
         user <- configure("user")
         password <- configure("password")
       } yield (host, user, password)
setupConnection: scalaz.Kleisli[Option,Map[String,String],(String, String, String)]
  • type StateTReaderTOption[C, S, A] = StateT[({type l[+X] = ReaderTOption[C, X]})#l, S, A]
    • StateT[l, S, A] where AnyVal { type l[+X] = ReaderTOption[C, X]} こんな感じ
    • StateだからS => (S, A)みたいのを取り扱って、Readerでlにラップするって感じか
    • StateTReaderTOption[C, S, A]な時、StateTReaderTOption.flatMap{ s: S => ..}で、S=List[A]にすると、こいつの状態を変化させる(言い方おかしいか)事でStackとかを実装出来る
  • applicative functorは最初idiomと名付けられた idiomatic <=> applicative
  • ScalazはMonoid[m].applicativeを実装して、どんなMonoidでもapplicativeに変換出来る:
    • monoidal applicative functor
    • ↓ Monoid.applicative
final def applicative: Applicative[({type λ[α]=F})#λ] = new Applicative[({type λ[α]=F})#λ] with SemigroupApply {
  def point[A](a: => A) = zero
}
  • Applicative同士(F,G)の積(product) = [x](F[x], G[x]])はApplicative
    • Applicative[List].product[Option].point(1) = (List(1),Some(1)): (List[Int], Option[Int])
  • 合成した[x]F[G[x]]もApplicative
    • Applicative[List].compose[Option].point(1) = List(Some(1)): List[Option[Int]]
  • Int => Int を Int => A として扱うことで applicative として扱えることが知られている:
scala> Applicative[Function1[Int, Int]]
<console>:14: error: Int => Int takes no type parameters, expected: one
Applicative[Function1[Int, Int]]
^
scala> Applicative[({type l[A]=Function1[Int, A]})#l]
res14: scalaz.Applicative[[A]Int => A] = scalaz.std.FunctionInstances$$anon$2@56ae78ac})]
  • HaskellでのFree
    • data Free f r = Free (f (Free f r)) | Pure r
instance (Functor f) => Monad (Free f) where
    return = Pure
    (Free x) >>= f = Free (fmap (>>= f) x)
    (Pure r) >>= f = f r
  • Freeのbindを読み解く: Scalazの中でFreeはReturnSuspendGosubの直和でbindの結果は常にGoSubになる
    • 先に各々の定義と、bindで使うgosub
    • Freeコンストラクタ
      • Gosub: aが値で、aの中身を変換するfが本体って感じで計算途中
      • Suspend: Freeのコンストラクタ
      • Return: Free.Pure
    • gosub: Gosubを返す関数(そのままだった)
object Free extends FreeInstances with FreeFunctions {
  /** Return from the computation with the given value. */
  private[scalaz] case class Return[S[_], A](a: A) extends Free[S, A]
  /** Suspend the computation with the given suspension. */
  private[scalaz] case class Suspend[S[_], A](a: S[Free[S, A]]) extends Free[S, A]
  /** Call a subroutine and continue with the given function. */
  private sealed abstract case class Gosub[S[_], B]() extends Free[S, B] {
    type C
    val a: () => Free[S, C]
    val f: C => Free[S, B]
  }
  def gosub[S[_], A, B](a0: () => Free[S, A])(f0: A => Free[S, B]): Free[S, B] =
    new Gosub[S, B] {
      type C = A
      val a = a0
      val f = f0
    }
...
  • でもってflatMapは以下のような処理が行われる
    • thisがGosubの時: Gosubはaが値で、aの中身を変換するfが本ってて感じ
      • aはそのまま、それと"次の計算"内容を渡したGosubを返す
      • "次の計算"とは、何かを引数に自身が持つ関数a.fに適用したのと、新しい計算処理fを渡したGosubとなる
    • thisがSuspendorReturnの時
      • 自身をaに渡し、Freeを生成する計算fをまとめてgosubに渡し、Gosubを作る
final def flatMap[B](f: A => Free[S, B]): Free[S, B] = this match {
  case a @ Gosub() => gosub(a.a)(x => gosub(() => a.f(x))(f))
  case a           => gosub(() => a)(f)
}
  • ↑所感
    • なんかあれだな、Gosubに処理を渡すけどそいつもFreeだから、Freeなままって、まぁ...まぁなるほどって感じ
    • Scalazのデータ構造の作り方の問題から見え方が変わってるかもしれない
  • Freeモナドのまとめ?
    • データが末端に来る全ての再帰データ型に使えるモデル Free モナドは変数が末端にある式木で、flatMap は変数の置換にあたる

ほー

  • 13日目(importガイド)

    Scala では import は 2つの目的で使われる: 1. 値や型の名前をスコープに取り込むため。 2. implicit をスコープに取り込むため。 implicit には僕が考えられる限り 4つの使い方がある: 1. 型クラスインスタンスを提供するため。 2. メソッド演算子を注入するため。(静的モンキーパッチ) 3. 型制約を宣言するため。 4. 型の情報をコンパイラから取得するため。 implicit は以下の優先順位で選択される: 1. プレフィックス無しでアクセスできる暗黙の値や変換子。ローカル宣言、import、外のスコープ、継承、および現在のパッケージオブジェクトから取り込まれる。同名の暗黙の値があった場合は内側のスコープのものが外側のものを shadow する。 2. 暗黙のスコープ。型、その部分、および親型のコンパニオンオブジェクトおよびパッケージオブジェクト内で宣言された暗黙の値や変換子。

scalaz.Scalaz._

以下のtraitをmixinして、importすることで色んなimplicitや関数・演算子をグローバルに用いれるようにしている

  • StateFunctions
    • get/putとかその辺の関数をグローバル関数として扱えるようにする
  • std.AllFunctions
    • ListFunctionsとかなんか色々スコープに取り込む系
  • IdInstances
  • std.AllInstances
    • 標準データ構造に対する型クラスのインスタンスのミックスイン
    • AnyValInstances, OptionInstances, ListInstances,...
  • syntax.ToTypeClassOps
  • syntax.ToDataOps
    • Scalazで定義されるデータ構造のために注入される演算子を導入: Idの|>とかTreeの1.node, 2.leafとか他にも1.success[String]とか
  • syntax.std.ToAllStdOps
    • Salaの標準型にメソッド演算子を導入
    • ToBooleanOps, ToOptionOpsとかmixinされてる
    • OptionOpsで1.some | 2とか出来る

圏論

前に圏論勉強会 @ ワークスアプリケーションズ見たし適当に流す
(参加出来るとこでこの勉強会もっかいして欲しい)

  • 圏、有限集合、射、対象
  • ここでは射mapを射arrowとして用いる
  • 射fに対して、fのdomain A -f-> B fのcodomain
  • domain = codomainの射を自己順同型射(endomorphism)
  • 集合Aの全てのaにおいてf(a)=aであるものを恒等射(identity arrow) 1_A
  • 圏の変化を全て担ってるのが射の合成(composition of maps)
    • scala.Function1のandThenかcompose
    • A -g-> A -f-> B <=> A -f∘g-> B <=> fとgの合成射
  • 圏の構成要素: 単位元律(The identity laws)と結合律(The associative law)を満たす
    • 対象 objects: A,B,C
    • 射 arrows: f: A => B
    • 恒等射 identity arrows: 1_A: A => A
    • 射の合成
  • 単集合 singleton: 唯一の要素elementのみを持つ集合 <=> 1
    • 点pointは1 => Xという射
    • Scalaでは(): Unit <=> 値とはUnit => Xである
  • 関数型プログラミングをサポートする言語における第一級関数は、関数を値として扱うことで高階関数を可能とする。圏論は逆方向に統一して値を関数として扱っている。 - なるほどたしかに

  • 同型射(isomorphism): f: A => Bに対して g∘f=1_A とf∘g=1_B の両方を満たすg: B => Aが存在する時のf
  • 1つでも同型射f: A => Bが存在する時、2つの対象AとBは同型(ispmorphic)
    • ScalazではIsomorphismsのIsoや集合の時はtype IsoSet[A, B] = Iso[Function1, A, B]
  • 決定問題(determination problem / extension)
    • f: A => B, h: A => C、h=g∘fであるときのgを全て挙げよ
  • 選択問題(choice problem / lifting)
    • g: B => C, h A => C, h=g∘fであるときのfを挙げよ???(何か違う気がするから後で見る)
  • レトラクション retraction
    • f: A => B、r∘f=1_Aが成り立つ射r: B => Aのこと
  • セクション section
    • f: A => B, f∘s=1_Bが成り立つ射s: B => Aのこと
  • 全射 surjective
    • f: A => Bに関して「y: T => Bに対してf∘x=yが成り立つ射x: T => Aが存在する」時、「fはTからの射に関して全射
  • 単射 injective
    • 「任意の射のペアx1: T => Aとx2: T => Aに対してf∘x1 = f∘x2ならばx1 = x2である」時、「fはTからの射に関して単射
  • モノ射 monomorphism
    • 射fが全てのTからの射に対して単射である時、fは単射である、またはモノ射であるという
  • エピ射 epimorphism: 全射の一般形
    • 射fが「任意の射のペアt1: T => Aとt2: T => Aに対してt1∘f = t2∘fならばt1 = t2 である」という条件が全てのTに成り立つ時、エピ射であるという
  • 自己同型射 endmorphism
    • 自己準同型 endomorphismであり、かつ同型 isomorphismである射のこと
  • 冪等射
    • 自己順同型射 endomorphisについてe∘e=eが成り立つ時冪等射
  • 自己準同型についてTODO

色んな圏

具体的なの

  • Sets: 集合と全域関数の圏
  • Sets_fin: 全ての有限集合とその間の全域関数(上の方の例はこれ)
  • Post: 数学でよく見る構造的集合
    • 半順序集合 partially ordered set(poset)である集合Aは反射律、推移律、反対称律を満たす二項関係を持つ
    • 関数が単調(monotone)である限り、対象は圏の中にとどまるため、「構造」が保存される <- とどまる???
  • Cat: 圏と関手functorの圏
  • モノイド: 集合Mで、MxM=>Mの二項演算と特定の単位元(unit)を持ち、結合則単位元則(って言うのかな?)を満たす
    • ScalazのMonoidzeroを持ち、継承元のSemigroup(半群)が二項演算appendを持つ
      • ちなみに、結合則を満たさなくてもいい二項演算を持つのはマグマって言うんだっけな
  • Groups: 群
    • モノイドGのうち、全ての要素gに対して逆射を持つもの
    • Gは唯一つの対象を持つ圏で、全ての射が同型射
    • Scalazには無くて、Spireってのが内容被ってるらしいけど、今見たらSpireなかった

抽象的なの?

  • 普遍性 universal property / 普遍写像性 universal mapping property => UMP
    • 全ての射が正しく合成出来ること
  • 始対象 initial 0
    • 任意の対象Cに対して 0 => Cを満たす一意の射を持つ対象
  • 終対象 terminal 1
    • 任意の対象Cに対して C => 1を満たす一意の射を持つ対象
  • 全ての始対象(終対象)は同型を除いて一意
    • 同じ圏内に始対象C,C'があるならば...0と0'が一意に同型なのが明らか
  • Sets圏における始対象は空集合で、任意の単集合が終対象となる

  • 積について

    • 集合AとBがあるとき、AとBのデカルト積は順序対(ordered pairs)の集合となる
    • デカルト積???ペア?? こういうことらしい => AxB = {(a,b)|a∈A,b∈B}: in Sets
    • fst∘(a,b)=a, snd∘(a,b)=b
    • 積はcase classやタプルの基底となり、scala.Productにも関連
  • 任意の要素 c ∈ A × B に対して、c = (fst ∘ c, snd ∘ c) - 面白い

  • 任意の圏Cにおいて、対象P, A, Bに対し p_1: P => A, p_2: P => Bとなる時...
    • x_1: X => A, x_2: X => Bに対し x_1=p_\1μ かつ x_2=p_2μが成立する一意の射μ: X => Pが存在する(普遍)
  • AとBの積の全てが同型をの除いて一意

  • 双対性

    • 逆圏? opposite category / dual <=> 双対圏 <=> Cop
    • 任意の圏Cと同じ対象を持つが、Cop内の射はCではf: D => C
    • CopはCの射を形式的に逆向きにしたもの
  • 双対性原理
    • f∘g -> g∘f, ドメイン <-> コドメイン
    • 上記のように変換すると、任意の証明はその双対に対しても成り立つ
  • 余積 coproduct: 積の双対 <=> 直和とも言う (co-になる)
    • 積はscala.Product, case classなどの直積型
    • 余積は直和型 sum type, union type(, sealed trait)に関連する
  • ScalaA with B論理積なるほど確かに <- これも最近ねこはるさんのなんかあったな
    • Scalaz.UnionTypes、既に無かったので当時のを見る
    • 否定は A => Nothing
  • Scalazの\/も直和型、はい
  • ScalazにはCoproductもある: 型コンストラクタのためのEither?どゆこと?

  • 小さい圏と大きい圏

    • 任意の圏Cにおいて、Cの対象の集まりC_0と、Cの者の集まりC_1が"集合"である時、小さい圏という
    • その他の場合は大きい圏
  • Hom集合 Hom-set: Hom(A, B): 対象AとBの射の集合
    • 任意の圏 C は、C の全ての対象 X と Y について、HomC(X, Y) = { f ∈ C1 | f: X = Y } という集まりが集合であるとき、局所的に小さいといい、これを hom集合という

  • 自然変換 natural transformation: 関手の射
    • 圏C,Dについて、関手C=>Dを新たな圏の対象として考えて、これらの対象間の射を自然変換と呼ぶ
    • ScalazのNaturalTransformation