かなり自明です。型クラスを作成する必要があることは知っていmakeClassy
ますが、2つの間に違いはありません。
PS。両方のデフォルトの動作を説明するためのボーナスポイント。
かなり自明です。型クラスを作成する必要があることは知っていmakeClassy
ますが、2つの間に違いはありません。
PS。両方のデフォルトの動作を説明するためのボーナスポイント。
makeLenses
タイプのフィールドごとに 1 つのトップレベルの optic を作成します。アンダースコア ( ) で始まるフィールドを探し、_
そのフィールドに対して可能な限り一般的なオプティックを作成します。
Iso
.Lens
。Traversal
。makeClassy
タイプのすべての光学系を含む単一のクラスを作成します。このバージョンは、タイプを別のより大きなタイプに簡単に埋め込んで、一種のサブタイピングを実現するために使用されます。Lens
そして、Traversal
光学系は上記のルールに従って作成されます (Iso
はサブタイピングの動作を妨げるため除外されます)。
フィールドごとにクラス内の 1 つのメソッドに加えて、このクラスのインスタンスを他の型に簡単に派生させる追加のメソッドを取得します。他のすべてのメソッドには、最上位のメソッドに関してデフォルトのインスタンスがあります。
data T = MkT { _field1 :: Int, _field2 :: Char }
class HasT a where
t :: Lens' a T
field1 :: Lens' a Int
field2 :: Lens' a Char
field1 = t . field1
field2 = t . field2
instance HasT T where
t = id
field1 f (MkT x y) = fmap (\x' -> MkT x' y) (f x)
field2 f (MkT x y) = fmap (\y' -> MkT x y') (f y)
data U = MkU { _subt :: T, _field3 :: Bool }
instance HasT U where
t f (MkU x y) = fmap (\x' -> MkU x' y) (f x)
-- field1 and field2 automatically defined
これには、特定のタイプのすべてのレンズを簡単にエクスポート/インポートできるという追加の利点があります。import Module (HasT(..))
makeFields
指定された名前のフィールドを持つすべてのタイプ間で再利用されることを目的として、フィールドごとに 1 つのクラスを作成します。これは、タイプ間で共有できないフィールド名を記録するための解決策です。
免責事項: これは実際のコードでの実験に基づいています。プロジェクトを進めるのに十分な情報が得られましたが、より適切に文書化された回答を希望します。
data Stuff = Stuff {
_foo
_FooBar
_stuffBaz
}
makeLenses
foo
へのレンズアクセサーとして作成しますStuff
fooBar
(大文字の名前を小文字に変更します);makeFields
baz
クラスを作成しHasBaz
ます。Stuff
そのクラスのインスタンスを作成します。