2016年11月20日

ちゅーんさんがしてくれたLens型の解説

type Lens s -- 取り出したり設定する元の型 t -- 書き換えた後の型 a -- sが内包する型 b -- tが内包する型 続きを読む
0
ちゅーん @its_out_of_tune

@public_ai000ya 件のスライドは自分でもわかりにくいなぁと思うので、別の切り口で文章ベースで解説してみようと思います(続

2016-11-19 20:11:01
ちゅーん @its_out_of_tune

@public_ai000ya まず、Lensの型変数 s t a b のそれぞれの役割りについて確認していきましょう s : 取り出したり設定する元の型 t : 書きかえた後の型 a : sの内包する型 b : tの内包する型 (続

2016-11-19 20:14:06
ちゅーん @its_out_of_tune

@public_ai000ya Lensの機能は、次の二種類の操作のセットで実現していると考えられます 1) 取り出し操作 :: s -> a 2) 設定操作 :: b -> t (続

2016-11-19 20:17:28
ちゅーん @its_out_of_tune

@public_ai000ya sとtでわけている理由は、Hoge x の x の部分に y を設定すると Hoge y になるように、設定したい値によっては s の型とt の型が異なる事があるからと考えてもらえれば差しつかえないです。

2016-11-19 20:22:47
ちゅーん @its_out_of_tune

@public_ai000ya ここで少し視点を変えてみましょう。(x -> y) -> Hoge x -> Hoge y のような変換を我々は良く見ますね。そうです、fmapです。(続

2016-11-19 20:25:41
ちゅーん @its_out_of_tune

@public_ai000ya この時、 v :: X として f _ = v :: x -> X のような関数をfmapするとHoge x の x が何であっても、vを内包したHoge X を得ることが出来ますね。つまりfmap出来ればその要素へのSetは出来たも同然です。(続

2016-11-19 20:29:10
ちゅーん @its_out_of_tune

@public_ai000ya 取り出し操作と設定操作に話を戻しましょう。取り出し操作は良いとして、設定操作の方は不完全なのに気がついたでしょうか。 b -> t では設定先の元となる構造がありません。本来 s -> b -> t ないし b -> s -> t であるべき。(続

2016-11-19 20:34:53
ちゅーん @its_out_of_tune

@public_ai000ya s -> b -> t という関数に s を適用すれば、b -> t という変換が得られますね。s -> a があれば、部分適用で b -> t という関数も得る事ができますので、実質我々は s -> a と b -> t という二つの変換を(続

2016-11-19 20:38:58
ちゅーん @its_out_of_tune

@public_ai000ya 持っていることになります。我々が本当に欲しいのは s -> b -> t ですが、先程お話しした「fmapできればSetもできる」という話を思い出してください。ここに一つ、a -> b という変換を追加してみましょう。(続

2016-11-19 20:42:47
ちゅーん @its_out_of_tune

@public_ai000ya a -> b をmapしたい関数と考えれば、 (a -> b) -> s -> t というfmapに似た関数が得られ、この a -> b を「引数を捨てて任意の値を返す」関数にすれば、s に対して好きな b を Set して t を得られます(続

2016-11-19 20:45:23
ちゅーん @its_out_of_tune

@public_ai000ya はい。これで Set は出来たのですが、これだけだと s -> a という取り出し関数を持っているのにも関わらず、取り出すことが出来ません。その答えを探るため、実際の Lens の型とここまでで作った型を比べてみましょう(続

2016-11-19 20:47:24
ちゅーん @its_out_of_tune

@public_ai000ya 作った型 :: (a -> b) -> s -> t Lensの型 :: (a -> f b) -> s -> f t ここで f は「任意のFunctor」です。(続

2016-11-19 20:48:36
ちゅーん @its_out_of_tune

@public_ai000ya 実際のLensの型を使ってSetしたいのであれば簡単です、fをIdentityにすれば良いんです。 data Identity a = Identity a instance Functor Identity (続く

2016-11-19 20:51:03
ちゅーん @its_out_of_tune

@public_ai000ya fはFunctorなので、我々が既に持っている b -> t をfmapすれば f b -> f t が得られます。これはそのまま「b を s に Set する」処理ですね。(続

2016-11-19 20:53:37
ちゅーん @its_out_of_tune

@public_ai000ya で、Getしたい場合はどうするか、f が Constになれば良いんです。 data Const a b = Const a instance Functor Const (続

2016-11-19 20:55:34
ちゅーん @its_out_of_tune

@public_ai000ya bをConstにして、Const b b という型の値を得ます。んで、取り出し処理 f b -> f t を適用すると Const b b -> Const b t となりますが、Constのfmapは実質的に**何もしません** (続

2016-11-19 20:57:28
ちゅーん @its_out_of_tune

@public_ai000ya 訂正)すいません。s -> a で取り出した値をConstに入れるので、正しくは Const a b -> Const a t ですね。 (続

2016-11-19 20:59:09
ちゅーん @its_out_of_tune

@public_ai000ya a -> f b の部分を s -> a で取り出した値をConstに詰めるだけの処理(a -> Const a b)にすれば、最終的に Const a t が得られます。この値が持っている型はs -> aで取り出した a そのものです。(続

2016-11-19 21:01:11
ちゅーん @its_out_of_tune

@public_ai000ya まとめ Lensの型 :: (a -> f b) -> s -> f t (a -> f b) の部分に与える関数によってs -> ft の動作が変わる (続

2016-11-19 21:03:18
ちゅーん @its_out_of_tune

@public_ai000ya a -> Identity b を与えるとSet a -> Const a b を与えるとGet 後は具体的なsを与えてやればおk。メンション汚し失礼しました以上がLensの仕組みですが、何か質問あればおこたえします(了

2016-11-19 21:04:23
ちゅーん @its_out_of_tune

@public_ai000ya ああ、そうですね、間違えてます。

2016-11-19 21:48:00
ちゅーん @its_out_of_tune

@public_ai000ya そうです。Const a b の b は型「だけ」しかないので、実質 Const a b = a です。

2016-11-19 21:59:23
ちゅーん @its_out_of_tune

@public_ai000ya そうです。Identity a は a と同値なので、f が無い場合と同じ理屈でset出来ます。

2016-11-19 22:17:16

コメント

コメントがまだありません。感想を最初に伝えてみませんか?