Haskell 为什么所有镜头都匹配Foldl.Handler类型?
根据: 任何透镜、横向或棱镜都将作为处理程序进行类型检查Haskell 为什么所有镜头都匹配Foldl.Handler类型?,haskell,fold,haskell-lens,Haskell,Fold,Haskell Lens,根据: 任何透镜、横向或棱镜都将作为处理程序进行类型检查 有人可能会说,因为lens允许任何不是常量的函子,所以只有lens的子集应该进行类型检查。为什么那句话不正确?你把方向搞错了。这里描述的光学元件都是这种形式 type Foo s t a b = forall f. SomeConstraints f => (a -> f b)-> (s -> f t) 小fib,对于棱镜来说,它应该使用任意的选项profunctor,但是->是这种结构的典型示例,因此我们可以
有人可能会说,因为lens允许任何不是
常量的函子
,所以只有lens的子集应该进行类型检查。为什么那句话不正确?你把方向搞错了。这里描述的光学元件都是这种形式
type Foo s t a b = forall f. SomeConstraints f => (a -> f b)-> (s -> f t)
小fib,对于棱镜来说,它应该使用任意的选项
profunctor,但是->
是这种结构的典型示例,因此我们可以专门化棱镜,使其仅在这些profunctor之间工作。这个过程合法的原因与我们将要用f
做的是一样的,所以暂停怀疑一分钟,继续读下去
现在,如果我们将s
和t
实例化为a
和a
和b
实例化为b
,那么我们得到
forall f. SomeConstraints f => (b -> f b) -> (a -> f a)
这意味着,如果我们有一些光学元件,比如透镜、棱镜或导线,我们可以实例化它的类型参数,这样它几乎是以处理程序的形式出现的。唯一的区别是,只要满足我们选择的约束条件,我们的产品就保证适用于任何f
。如果我们知道Constant(Endo x)
满足这些约束,那么我们可以默默地专门化该光学元件,使其仅与f
一起工作。这只是普通的多态实例化!由于常数a
是一个函子
和一个应用程序
,它将与任何镜头或遍历一起工作。这种隐式的子类型和实例化是使镜头包工作的核心,通过让所有这些东西透明,Haskell让我们混合和匹配抽象,它将自动确定我们正在使用的任何一组光学器件的“最大下限”
整个事情归结为这样一个事实:在Haskell中,如果我们有e::forall t。T
,那么对于任何适当种类的tau
我们也有e::[tau/T]T
。一旦我们加入类型约束,就会出现一些问题,但总的来说,在Haskell中,类型应用程序在默认情况下是静默的,这是事实。你把方向搞错了。这里描述的光学元件都是这种形式
type Foo s t a b = forall f. SomeConstraints f => (a -> f b)-> (s -> f t)
小fib,对于棱镜来说,它应该使用任意的选项
profunctor,但是->
是这种结构的典型示例,因此我们可以专门化棱镜,使其仅在这些profunctor之间工作。这个过程合法的原因与我们将要用f
做的是一样的,所以暂停怀疑一分钟,继续读下去
现在,如果我们将s
和t
实例化为a
和a
和b
实例化为b
,那么我们得到
forall f. SomeConstraints f => (b -> f b) -> (a -> f a)
这意味着,如果我们有一些光学元件,比如透镜、棱镜或导线,我们可以实例化它的类型参数,这样它几乎是以处理程序的形式出现的。唯一的区别是,只要满足我们选择的约束条件,我们的产品就保证适用于任何f
。如果我们知道Constant(Endo x)
满足这些约束,那么我们可以默默地专门化该光学元件,使其仅与f
一起工作。这只是普通的多态实例化!由于常数a
是一个函子
和一个应用程序
,它将与任何镜头或遍历一起工作。这种隐式的子类型和实例化是使镜头包工作的核心,通过让所有这些东西透明,Haskell让我们混合和匹配抽象,它将自动确定我们正在使用的任何一组光学器件的“最大下限”
整个事情归结为这样一个事实:在Haskell中,如果我们有e::forall t。T
,那么对于任何适当种类的tau
我们也有e::[tau/T]T
。一旦我们加入类型约束,就会有一些问题,但总的来说,在Haskell中,类型应用程序默认是静默的