11

我一直在阅读A wreq 教程

镜头提供了一种关注 Haskell 值的一部分的方法。比如Responsetype有一个responseStatuslens,重点关注服务端返回的状态信息。

ghci> r ^. responseStatus
Status {statusCode = 200, statusMessage = "OK"}

^.运算符将一个值作为其第一个参数,将一个镜头作为其第二个参数,并返回镜头聚焦的值部分。

我们使用函数组合来组合镜头,这使我们能够轻松地专注于深度嵌套结构的一部分。

ghci> r ^. responseStatus . statusCode
200

我想不出一种方法,如何使用这种参数顺序完成的函数组合可以按该顺序处理嵌套结构。

看:r ^. responseStatus . statusCode可能是r ^. (responseStatus . statusCode)(r ^. responseStatus) . statusCode

在第一个中说我们构造了一个函数,它首先处理statusCode(从记录中获取它Status? - 正如我可以从显示的值中推断出来的那样Status {statusCode = 200, statusMessage = "OK"}),然后将它传递给responseStatus必须处理响应状态的函数。所以,反过来说:实际上,状态码是响应状态的一部分。

第二次阅读对我来说也没有意义,因为它也首先处理状态代码。

4

1 回答 1

13

的正确读法r ^. responseStatus . statusCoder ^. (responseStatus . statusCode)。这是很自然的,因为函数组合在应用于两个参数时返回一个函数,因此(r ^. responseStatus) . statusCode必须返回一个函数,而不是任何可以打印出来的值。

这仍然留下了为什么镜头以“错误”顺序组成的问题。由于镜头的实现有点神奇,我们来看一个更简单的例子。

first是一个映射到对的第一个元素的函数:

first :: (a -> b) -> (a, c) -> (b, c)
first f (a, b) = (f a, b)

做什么map . firstfirst接受一个作用于第一个元素的函数,并返回一个作用于一对的函数,如果我们以这种方式将类型括起来,则更明显:

first :: (a -> b) -> ((a, c) -> (b, c))

另外,回忆一下 的类型map

map :: (a -> b) -> ([a] -> [b])

map接受作用于元素的函数并返回作用于列表的函数。现在,f . g首先应用g然后将结果提供给f. Somap . first获取一个作用于某种元素类型的函数,将其转换为作用于对的函数,然后将其转换为作用于对列表的函数。

(map . first) :: (a -> b) -> [(a, c)] -> [(b, c)]

first并且map两者都将作用于结构的一部分的功能转变为作用于整个结构的功能。map . first其中,整体结构是为了什么成为first焦点map

(map . first) (+10) [(0, 2), (3, 4)] == [(10, 2), (13, 4)]

现在来看看镜头的类型:

type Lens = forall f. Functor f => (a -> f b) -> (s -> f t)

现在尝试忽略这些Functor位。如果我们稍微眯起眼睛,这类似于mapand的类型first。发生这种情况时,镜头也会将作用于部分结构的功能转换为作用于整个结构的功能。在上面的签名s中表示整个结构并a表示它的一部分。由于我们的输入函数可以改变ato的类型b(用 表示a -> f b),所以我们还需要t参数,大致意思是“s我们改成a里面的类型b”。

statusCodeInt是将作用于 a 的函数转换为作用于a的函数的透镜Status

statusCode :: Functor f => (Int -> f Int) -> (Status -> f Status)

responseStatus将作用于 aStatus的函数转换为作用于 a 的函数Response

responseStatus :: Functor f => (Status -> f Status) -> (Response -> f Response)

的类型responseStatus . statusCode遵循与我们看到的相同的模式map . first

responseStatus . statusCode :: Functor f => (Int -> f Int) -> (Response -> f Response)

究竟是如何工作的还有待观察^.。它与镜头的核心机制和魔力密切相关;我不会在这里重复它,因为有很多关于它的著作。对于介绍,我建议您查看这个这个,您也可以观看这个出色的视频。

于 2015-03-08T18:25:48.067 回答