data-class 相当于 `_1` 风格的元组镜头快捷方式?

data-class equivalent of `_1`-style tuple lens shortcut?

根据其 documentation,Haskell 的 lens 库的 _1 为元组提供了一个镜头。

对于数据记录,还有其他几个功能,例如makeLenses,根据记录的字段名称自动生成镜头。

不幸的是,我正在处理没有命名字段的数据 类,这意味着 makeLenses 对我来说不合适。 这让我想知道。 _1 似乎很方便,但正如其文档中所暗示的那样,似乎不适用于数据 类。是否有同等程度的便利?

> :set -package lens
> import Control.Lens
> (1,2) ^. _1
1
> data Bar = Bar String deriving Show
> bar = Bar "abc"
> bar ^. _1

<interactive>:271:1: error:
    • Non type-variable argument in the constraint: Field1 Bar Bar b b
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall b. Field1 Bar Bar b b => b

添加 FlexibleContexts 扩展,我反而面临另一个错误:

bar ^. _1

<interactive>:6:1: error:
    • No instance for (Field1 Bar Bar () ()) arising from a use of ‘it’
    • In the first argument of ‘print’, namely ‘it’
      In a stmt of an interactive GHCi command: print it

Field1 有一个默认的泛型实现,所以你可以自己添加一个实例:

{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)

data Bar = Bar String deriving (Show, Generic)

instance Field1 Bar Bar String String

generic-lens 也提供相同的功能,而不需要样板实例。 _1 被称为 position @1(来自 Data.Generics.Product(.Positions))。