为什么所有 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
进行的操作相同,所以暂停一分钟的怀疑并继续阅读
现在,如果我们将 s
和 t
实例化为 a
,将 a
和 b
实例化为 b
,那么我们得到
forall f. SomeConstraints f => (b -> f b) -> (a -> f a)
现在这意味着如果我们有一些光学器件,如透镜、棱镜或遍历器,我们可以实例化它的类型参数,这样它几乎是 Handler
的形式。唯一的区别是我们的保证适用于任何 f
只要它满足我们选择的约束。如果我们知道 Constant (Endo x)
满足这些约束,那么我们可以默默地专门化该光学器件以 仅与 f
一起工作。这只是普通的旧多态实例化!由于 Constant a
是 Functor
和 Applicative
,因此它适用于任何镜头或遍历。这种隐式子类型化和实例化是使镜头包工作的核心,通过让所有这些东西透明 Haskell 让我们混合和匹配抽象,它会自动解决任何一组的 "greatest lower bound"我们正在使用的光学器件。
整个事情归结为这样一个事实,即在 Haskell 中,如果我们有 e :: forall t. T
,那么对于任何适当种类的 tau
,我们也有 e :: [tau/t]T
。一旦我们加入类型约束,就会有一些皱纹,但总的来说,这只是类型应用程序在 Haskell.
中默认情况下是静默的。
根据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
进行的操作相同,所以暂停一分钟的怀疑并继续阅读
现在,如果我们将 s
和 t
实例化为 a
,将 a
和 b
实例化为 b
,那么我们得到
forall f. SomeConstraints f => (b -> f b) -> (a -> f a)
现在这意味着如果我们有一些光学器件,如透镜、棱镜或遍历器,我们可以实例化它的类型参数,这样它几乎是 Handler
的形式。唯一的区别是我们的保证适用于任何 f
只要它满足我们选择的约束。如果我们知道 Constant (Endo x)
满足这些约束,那么我们可以默默地专门化该光学器件以 仅与 f
一起工作。这只是普通的旧多态实例化!由于 Constant a
是 Functor
和 Applicative
,因此它适用于任何镜头或遍历。这种隐式子类型化和实例化是使镜头包工作的核心,通过让所有这些东西透明 Haskell 让我们混合和匹配抽象,它会自动解决任何一组的 "greatest lower bound"我们正在使用的光学器件。
整个事情归结为这样一个事实,即在 Haskell 中,如果我们有 e :: forall t. T
,那么对于任何适当种类的 tau
,我们也有 e :: [tau/t]T
。一旦我们加入类型约束,就会有一些皱纹,但总的来说,这只是类型应用程序在 Haskell.