scalaz - Kleisli

[独習Scalaz - モナディック関数の合成](http://eed3si9n.com/learning-scalaz/ja/Composing-monadic-functions.html)のメモ。

> Scalaz には Kleisli と呼ばれる A => M[B] という型の関数に対する特殊なラッパーがある:

## 定義

さっそくKleisliの定義をみてみる。

```scala
final case class Kleisli[M[_], A, B](run: A => M[B])
```

使い方をみてみよう。

## 使い方

```scala
Kleisli { a: Int => Option(a + "!") } run 1
// Some(1!)
```

たしかに `A => M[B]` だ。

Kleisliは、関数に変換できるようなimplicitが定義されている。

```scala
val f: Int => Option[String] = Kleisli { a: Int => (a + "!").some }
f(1) // Some(1!)
```

ちなみにOptionだけはalias `=?>` が定義されている。

```scala
val k: Int =?> String = Kleisli { a: Int => Option(a + "!") }
// Kleisli[Option, Int, String]
```

## インスタンスの関数

ひたすらに関数を使ってみる。

**andThen** (alias: **>=>**) 

`Kleisli[M, A, B] >=> Kleisli[M, B, C]` だ

```scala
Kleisli { a: Int => Option(a + "!") } >=> Kleisli { b: String => Option(b + "?") } run 1
// Some(1!?)
```

**compose** (alias: **<=<**)

```scala
Kleisli { a: String => Option(a + "!") } <=< Kleisli { a: Int => Option(a + "?") } run 1
// Some(1?!)
```

**>==>**: 関数だけ渡せばandThenと同じ

```scala
Kleisli { a: Int => Option(a + "!") } >==> { b: String => Option(b + "?") } run 1
// Some(1!?)
```

**<==<**: 関数を渡すだけでcomposeと同じ

```scala
Kleisli { a: String => Option(a + "!") } <==< { a: Int => Option(a + "?") } run 1
// Some(1?!)
```

**traverse**: これは `F[A] => M[F[B]]` な関数だ

```scala
Kleisli { a: Int => Option(a + "!") } traverse List(1)
// Some(List(1!))
```

**=<<**: 値を取り出してKeisliに適用してくれる `M[A] => M[B]` な関数だ

```scala
Kleisli { a: Int => Option(a + "!") } =<< Option(1)
// Some(1!)
```

**map**: `B => C` にするいつもの関数だ

```scala
Kleisli { a: Int => Option(a + "!") } map { _ + "?" } run 1
// Some(1!?)
```

**flatMap**: `B => Kleisli[M, A, C]` にするいつもの関数だ

```scala
Kleisli { a: Int => Option(a + "!") } flatMap { b: String => Kleisli { a: Int => Option("c") } } run 1
// c
```

**mapK**: `M[B] => N[C]` にする関数だ。Nは1つの型をとる何か。

```scala
Kleisli { a: Int => Option(a + "!") } mapK { mb: Option[String] => mb.toList } run 1
// List(1?)
```

**flatMapK**: `B => M[C]` にする関数だ

```scala
Kleisli { a: Int => Option(a + "!") } flatMapK { b: String => Option("c") } run 1
// c
```
え? mapKは `M[B] => N[C]` だから、flatMapKは `M[B] => Kleisli[N, A, C]` だと思ったんだけど...?

**state**: StateTに変換

```scala
Kleisli { (_:Int).some }.state
// StateT[Option,Int,Int]
```

**liftMK**: モナドの合成

```scala
Kleisli { (_:Int).some }.liftMK[ListT]
// ListT[Option,A],Int,Int]
```

**local**: 最初に渡した関数を適用する

```scala
Kleisli { a:Int => (a + 2).some } local { a:Int => a * 2 } run 1
// Some(4)
```

**endo**: TODO

**liftF**: TODO

## オブジェクトの関数

**kleisliU**: 型を2つとる型でも

```scala
Kleisli.kleisliU { a: Int => Writer("ok", a) } run 1
// WriterT((ok,1))
```

これは便利だ...。

**ask**: pointみたいなものだ

```scala
Kleisli.ask[Option, Int]
// Kleisli[Option,Int,Int]
```

**local**: インスタンスの関数であったのと同じ感じだ。最初に渡した関数を評価する。 

```scala
Kleisli.local({a: Int => a + 2})(Kleisli { a: Int => (a * 2).some }) run 1
// Some(6)
```

## liftについて

liftやunliftは複雑だからよく見てみることにしよう。

**lift**: Mをliftする関数だ。Applicativeだったらなんでもいいようだ。

```scala
val k= Kleisli { a: Int => Option(a + "!") }.lift[List]
// Kleisli[List[Option[_]], Int, String]
k(1)
// List(Some(1!))
```

**unlift**: liftの逆だ。

```scala
val k = Kleisli { a: Int => Option(a + "!") }.lift[Tree]
// Kleisli[Tree[Option], Int, String] MをTreeにlift

k.unlift[Tree, Option]
// Kleisli[Option, Int, String] unliftされた
```

こいつはちょっと複雑だ。

```scala
def unlift[N[_], FF[_]](implicit M: Comonad[N], ev: this.type <~< Kleisli[λ[α => N[FF[α]]], A, B]): Kleisli[FF, A, B]
```

Comonadのimplicitが必要なのでTreeにした。他にもComonadにはWriterやFunction1などの定義があった。

`<~<` はLiskov内の関数だがよく分かってない..。なんでここで必要なんだろうか。難しい...

というかComonadのインスタンス少ないのか..haskellもそんなもんなんだろうか...分からん。

**unliftId**: unliftのId固定版だ

```scala
val k = Kleisli[({type λ[A]=Writer[String, A]})#λ, Int, Int] { x: Int => Writer("ok", x) }
// Kleisli[WriterT[Id, String, A], Int, Int] (IdとWriterTが合成された状態だ)

val k2 = k.unliftId[({type λ[A]=Writer[String,A]})#λ]
// Kleisli[Id, Int, Int] (Writerをunliftできた)

k2 run 1
// 1: Id[Int]
```

lift/unliftできてる。

## 他に

あとKleisliはMonoidでもあるようだ。

```scala
val k = Kleisli { (_:Int).some }
k |+| k |+| k run 1
// Some(3)
```

他にもApplyとか色々インスタンスもってるようだ。