为什么所有 Lens 都匹配 Foldl.Handler 类型?

Why do all Lens match Foldl.Handler type?

根据Control.Foldl documentation

Any lens, traversal, or prism will type-check as a Handler

type Handler a b 
   = forall x. (b -> Constant (Endo x) b) -> a -> Constant (Endo x) a

有人可能会声称,由于 lens 允许任何 Functor 不是 Constant,因此只有 lens 的子集应该进行类型检查。为什么这个说法不正确?

你把方向搞混了。那里描述的光学器件都是

形式
 type Foo s t a b = forall f. SomeConstraints f => (a -> f b)-> (s -> f t)

小谎言,对于棱镜,它应该与任意 Choice profunctor 一起工作,但是 -> 是这种结构的典型示例,因此我们可以专门化棱镜只适用于这些profunctors。这个过程合法的原因与我们将要对 f 进行的操作相同,所以暂停一分钟的怀疑并继续阅读

现在,如果我们将 st 实例化为 a,将 ab 实例化为 b,那么我们得到

 forall f. SomeConstraints f => (b -> f b) -> (a -> f a)

现在这意味着如果我们有一些光学器件,如透镜、棱镜或遍历器,我们可以实例化它的类型参数,这样它几乎是 Handler 的形式。唯一的区别是我们的保证适用于任何 f 只要它满足我们选择的约束。如果我们知道 Constant (Endo x) 满足这些约束,那么我们可以默默地专门化该光学器件以 仅与 f 一起工作。这只是普通的旧多态实例化!由于 Constant aFunctorApplicative,因此它适用于任何镜头或遍历。这种隐式子类型化和实例化是使镜头包工作的核心,通过让所有这些东西透明 Haskell 让我们混合和匹配抽象,它会自动解决任何一组的 "greatest lower bound"我们正在使用的光学器件。

整个事情归结为这样一个事实,即在 Haskell 中,如果我们有 e :: forall t. T,那么对于任何适当种类的 tau,我们也有 e :: [tau/t]T。一旦我们加入类型约束,就会有一些皱纹,但总的来说,这只是类型应用程序在 Haskell.

中默认情况下是静默的。