generated at
Lens











ややこいので以下のように呼び分けよう
Lens
そもそもある概念
HaskellでLensを実装したpackage
具体的な型





この辺が良いらしい




自分で定義した型に対してsetterやgetterなどの便利関数を自動生成する
TSではclassを作って、そのインスタンスに対して、データを更新したりgetしたりするが、それと同じようなことを関数型の世界でも行う
関数合成などのデザインもきれい
ネストがあるタプルやレコードの操作時にありがたくなる
逆にネストがなければそんなにありがたくない



tutorial







Lensを使って生成したgetterやsetterのことを「lenses」と呼ぶっぽいmrsekut
まあ単数形でもいいけど、わかり易さのために複数形にしてるmrsekut
lensesを作る「lens関数」もある
「Lens」と呼んで指す対象が多すぎるmrsekut
package名
生成されたgetter/setter
特定の1つの関数



基本的にはこれさえ抑えておけばできる
lensesを作る
makeLens or makeFields
fmap
多くの場合 makeFields を使えばいい?mrsekut
lensesの合成
普通に .
アクセスする
view
over
set



over :: ASetter s t a b -> (a -> b) -> s -> t
これはsetter

view :: MonadReader s m => Getting a s a -> m a
これはgetter
^. というエイリアスがある

hs
data Atom = Atom { _element :: String, _point :: Point } deriving (Show) data Point = Point { _x :: Double, _y :: Double } deriving (Show) $(makeLenses ''Atom) $(makeLenses ''Point) -- use > let atom = Atom { _element = "C", _point = Point { _x = 1.0, _y = 2.0 } } > view (point . x) atom 1.0 ghci> atom^.point.x 1.0 ghci> atom^.point^.x 1.0 > over (point . x) (+1) atom Atom {_element = "C", _point = Point {_x = 2.0, _y = 2.0}}
以下は全て同じ意味
hs
view (point . x) atom atom^.point.x atom^.point^.x
.^ view のエイリアスなので、1行目と2行目がおなじになるのはわかる
3行目は、統一感のためにあるのだろうか
普通はどれを使うんだろうmrsekut
2行目かな
関数合成
Lens' 型で単純化して見るとわかりやすいmrsekut
型の前後は、普通の関数合成 . と同じ感じになっっているmrsekut
hs
point :: Lens' Atom Point x :: Lens' Point Double point . x :: Lens' Atom Double



Lens Laws
getterとsetterが以下の3つを満たす
set s (get s) == s
get (set s v) == v
get (set (set s v1) v2) == v2






フィールド系
makeLenses '' Hoge
setter
+~ , -~ , *~
フィールドが数値の場合に使える
+~10 なら元の値に10を加算する
例.hs
{-# LANGUAGE TemplateHaskell #-} data Par = Par { _foo :: Int, _chi :: Chi } deriving (Show, Eq) data Chi = Chi { _piyo :: String } deriving (Show, Eq) makeLenses ''Par let par = (Par 1 (Chi "child")) -- getter _foo par -- 普通のアクセス par^.foo -- Lensでのアクセス par^.chi^.piyo -- チェーンもできる ("Piyo", par)^._2.foo -- タプル系の関数と組み合わせる -- setter par&foo.~3 -- 3に変更 par&foo+~10 -- 10加算する
makeFieldsを使う
mkLabelというのもあるらしい





















タプル系
(^.) :: s -> Getting a s a -> a
演算子
view 関数のエイリアス
_1 : 1番目を取得
hs
(1, ('a', 'b', ("Hoge", "Piyo")), 2)^. _2 . _3 . _1
関数合成 (.) をOOPのmethodに見立てているの面白いmrsekut
(.~) :: ASetter s t a b -> b -> s -> t
値の変更
set 関数のエイリアス
hs
_1._2.~True $ ((1,2),3) -- ((1,True),3)
(&) :: a -> (a -> b) -> b
hs
((1,2),3)&_1._2 .~ True -- ((1,True),3)
値の変更
to
ネストの深い部分に関数を適用した結果を得る
hs
("hoge", ("a", "nya"))^._2._2.to length -- 3





以下の違いってなに
hs
$(makeLenses ''Atom) makeLenses ''Atom
$(..) って何の意味がある?順序とか?



Lensが型
合成可能なfunctional reference



実装が複数ある
何でもできるが、読み解くのが難しい
コンパクト
data-lensというパッケージもあるが、それは古いやつ



Lens内の型
Equality
Iso
Getter
Setter
Review






圏論


Lensの実装が気になる
実装読んでないけどけっこう難解?らしいmrsekut
後半






参考
概要がわかりやすい
Lensに関する大量の資料集
圏論に関するものもある
template haskellを使ってるので若干嫌われてる?