haskell - 组合函数时,通用量化和类型类约束会发生什么?

标签 haskell lenses rank-n-types

镜头can be composed就像任何普通函数一样。我们有:

Lens' a b = forall f . Functor f => (b -> f b) -> a -> f a

现在考虑这个例子:

(.) :: Lens' Config Foo -> Lens' Foo String -> Lens' Config String

展开我们得到:

(.) :: (forall f. Functor f => (Foo -> f Foo) -> Config -> f Config)
    -> (forall f. Functor f => (String -> f String) -> Foo -> f Foo)
    -> (forall f. Functor f => (String -> f String) -> Config -> f Config)

函数组合的类型为:

(.) :: (b -> c) -> (a -> b) -> (a -> c)

缺乏任何通用量化和类型类约束。现在我的问题是,编译器/类型检查器如何处理这两个功能,以便函数组合运算符可以用于组合镜头?

我的猜测是,只要函数与正在组合的两个函数匹配,就可以使用通用量化的函数和类型类约束。

最佳答案

为什么我们不看看会发生什么?考虑以下值:

(.) :: (b -> c) -> (a -> b) -> a -> c

foo :: Lens' A B

bar :: Lens' B C

foo的类型和bar将扩展为:

foo :: Functor f => (B -> f B) -> A -> f A

bar :: Functor g => (C -> g C) -> B -> g B

请注意,我遗漏了 forall f.部分因为它是隐式的。另外,我改了名字fg对于 bar以表明它与 f 不同对于 foo .

不管怎样,我们先申请(.)foo :

(.)     ::                 (b      ->    c)    -> (a ->    b)     -> a ->    c
                            |            |         |       |         |       |
                         --------     --------     |       |         |       |
                         |      |     |      |     |       |         |       |
foo     :: Functor f => (B -> f B) -> A -> f A     |    --------     |    --------
                                                   |    |      |     |    |      |
(.) foo :: Functor f =>                           (a -> B -> f B) -> a -> A -> f A

因此,(.) foo类型为 Functor f => (a -> B -> f B) -> a -> A -> f A 。如您所见,Functor约束只是按原样复制。

现在,我们申请(.) foobar :

(.) foo     :: Functor f =>    (a      -> B -> f B) ->     a      -> A -> f A
                       |        |         |    | |         |         |    | |
                       |     --------     |    | |         |         |    | |
                       |     |      |     |    | |         |         |    | |
bar         :: Functor g => (C -> g C) -> B -> g B      --------     |    | |
                                                        |      |     |    | |
(.) foo bar :: Functor g =>                            (C -> g C) -> A -> g A

因此,(.) foo bar类型为 Functor g => (C -> g C) -> A -> g A这意味着它是 Lens' A C 。如您所见Functor fFunctor g 相同这就是为什么一切顺利。

关于haskell - 组合函数时,通用量化和类型类约束会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46010198/

相关文章:

haskell - 了解(可遍历产品)类型

haskell - 镜头生成是否应该像实例一样对待

haskell - 这种类型是有效的 "rank-2 bifunctor"吗?

haskell - 对现有数据类型实现类型类约束

haskell - 从 "lens"的 map 获取多个结果

haskell - Haskell 有 "variables"吗?或者,读取配置数据的最简单方法?

haskell - 使用 IO.readLn 从 Haskell 中的标准输入读取单行

重新导出时的 Haskell 命名空间

haskell - 递归型镜头