使用镜头作为`map`

时间:2014-11-01 06:52:37

标签: haskell lenses

我想将此行代码map (^?! ix 0) [[0, 1], [4, 5], [9, 1]]转换为完全使用镜头,因此类似于[[0, 1], [4, 5], [9, 1]] & each . ix 0。但是,这些类型并不匹配。这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:10)

您可以使用

之一
Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] & each %~ (^?! ix 0)
[0,4,9]
Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. each . ix 0
[0,4,9]

第一个对应于您使用不安全的(^?!)运算符编写的内容,这意味着它可以给出错误。第二个是遗漏空列表更安全。

它们以不同的方式工作:第一个创建原始结构的修改版本,它更符合map的作用,并且可以用于非列表的结构。

第二个使用提供的镜头折叠创建结构的列表摘要;虽然它可以用于多种结构,但结果始终是一个列表。

您还可以将each替换为traverse(或者,正如@danidiaz指出的那样,稍微更为一般traversed)。前者适用于许多特殊事物,如元组,而后者适用于任何Traversable

答案 1 :(得分:10)

使用folded

Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. folded . ix 0
[0,4,9]

适用于任何Foldable

另外,如果您打算始终提取第一个元素,那么使用_head而不是Control.Lens.Cons的{​​{1}}遍历可能会更清楚。

ix