アップデート
ご質問のおかげで、 の次のバージョンにはControl.Lens.Iso
と が含ま firsting
れseconding
ます。
iso id id
少し醜く見えます。それを分解してみましょう。
type Iso s t a b =
forall f p . (Functor f, Profunctor p) =>
p a (f b) -> p s (f t)
--plain :: Iso s t s t
--plain = iso id id
plain :: (Functor f, Profunctor p) => p s (f t) -> p s (f t)
plain = id
したがって、実装を削減できます
firsting p = bimapping p id
これはおそらく最も簡潔な形式です。あなたが本当に必要最低限 のものに到達したい場合は、読み進めてください.
の定義をインライン化するbimapping
bimapping :: (Bifunctor f, Bifunctor g) => AnIso s t a b -> AnIso s' t' a' b' -> Iso (f s s') (g t t') (f a a') (g b b')
bimapping f g = withIso f $ \ sa bt -> withIso g $ \s'a' b't' ->
iso (bimap sa s'a') (bimap bt b't')
を使用して簡略化するfirst
と、次のようになります。
firsting p = withIso p $ \ sa bt ->
iso (first sa) (first bt)
これは特にわかりやすい表現だと思います。を使用withIso
しp
て同型を構成する 2 つの関数に分割し、 を使用first
してそれぞれを持ち上げて bifunctor の最初の引数に適用し、 でそれらをパッケージ化しますiso
。関連する bifunctor に、first
で実行できるよりも優れた処理を行う最適化が含まれているbimap
場合、これも を使用した実装よりも高速になりますbimapping
。
インライン化iso
すると
firsting p = withIso p $ \ sa bt ->
dimap (first sa) (fmap (first bt))
最後に、インライン化(おそらく行うべきではない をwithIso
掘り下げます)、Control.Lens.Internal.Iso
firsting p =
case p (Exchange id Identity) of
Exchange sa bt ->
dimap (first sa) (fmap (first (runIdentity #. bt)))
ちなみに、plain
冗長な文脈を除いた の型シグネチャは
plain :: p s (f t) -> p s (f t)
これはまったく同じです
plain :: Equality s t s t