3

Control.Lens.IsoIsos を有用な抽象化のさまざまな型引数に持ち上げるための多くの素晴らしい関数が含まれています。例えば:

  • mapping任意Functorの s
  • contramappingContravariantファンクタ用
  • dimappinglmappingおよびs rmapping_Profunctor
  • bimappingのためBifunctor

Isoanを a のfirst引数に持ち上げる関数を探していますBifunctorが、そこにはないようです。私は現在それを次のように定義しています:

firsting
  :: Bifunctor f
  => AnIso s t a b
  -> Iso (f s x) (f t y) (f a x) (f b y)
firsting p = bimapping p (iso id id)

この機能はすでにどこかに存在していますか、それともそれとbimapping p (iso id id)同じくらい優れていますか?

4

1 に答える 1

3

アップデート

ご質問のおかげで、 の次のバージョンにはControl.Lens.Iso と が含ま firstingsecondingます。


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)

これは特にわかりやすい表現だと思います。を使用withIsopて同型を構成する 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
于 2015-12-08T17:15:03.410 に答える