为什么索引镜头的定义方式如何?

use*_*465 6 haskell haskell-lens

这个reddit线程中有一些非常有用的解释,如何定义索引镜头,但我想知道细节.

因此,重点是索引镜头的定义使得它们也可以被视为非索引镜头.这两个类负责:

class (Choice p, Corepresentable p,
       Comonad (Corep p), Traversable (Corep p),
       Strong p, Representable p, Monad (Rep p),
       MonadFix (Rep p), Distributive (Rep p),
       ArrowLoop p, ArrowApply p, ArrowChoice p
       ) => Conjoined p where
  distrib :: Functor f => p a b -> p (f a) (f b)
  conjoined :: (p ~ (->) => q (a -> b) r) -> q (p a b) r -> q (p a b) r

class Conjoined p => Indexable i p where
  indexed :: p a b -> i -> a -> b
Run Code Online (Sandbox Code Playgroud)

问题:

0)为什么将索引镜片视为非索引镜片是有用的?爱德华(见上面的链接)说

这让我们删除了30多个组合名称,让我们共享一个组合器,用于大多数操作的索引和非索引版本.

那些组合器是什么?我很欣赏一些例子.

无论多么Conjoined聪明,我想它仍然更有效率(不需要捕获全内联,因此字典不会被传递)并且在可能的情况下灵活地使用非索引光学器件.事实上我看到了这个:

-- If you don't need access to the index, then 'mapped' is more flexible in what it accepts.
imapped :: IndexedSetter i (f a) (f b) a b
Run Code Online (Sandbox Code Playgroud)

(因为用一个法律class Functor f => FunctorWithIndex i f | f -> i取代imap (const id) ? id法律会更好imap (const f) ? fmap f吗?)

itraversed . itraversed忽略前一个索引并返回后一个索引的行为对我来说看起来相当隐蔽和混乱.这使类型推断和错误变得复杂.另外,我看到某个地方traversed . traversed对某些"工作"的定义不起作用,这是正确的吗?

我应该只为我的库编写索引光学器件并使用它,或者是否仍然需要提供组合器的索引和非索引变体?

1)Conjoin是一个非常巧妙的技巧,但它远非显而易见,并且它没有被记录.我想,有些人定义了他们自己的索引光学组合器(这是常见的吗?)并不知道他们应该使用conjoin.是否有可能以conjoin某种方式强制使用?

工作需要均匀MonadFix (Rep p)ArrowLoop p约束Conjoin吗?什么是distrib?它与它有什么关系Mapping

class (Traversing p, Closed p) => Mapping p where
  map' :: Functor f => p a b -> p (f a) (f b)
Run Code Online (Sandbox Code Playgroud)

什么是Conjoined ReifiedGetter对的实例?

2)是否有一个比临时结构更少的结构Indexable?说,像

class Functor f => StarLike p f | p -> f where
  runStarLike :: p a b -> a -> f b

type Indexable i p = (Conjoined p, StarLike p ((->) i)
Run Code Online (Sandbox Code Playgroud)