эквивалент класса данных ярлыка кортежного объектива в стиле _1? - PullRequest
2 голосов
/ 12 января 2020

В соответствии с документацией ,

библиотеки lens библиотеки _1 предоставляют линзу для кортежей.

Для записей данных вместо этого есть несколько других функций, таких как: makeLenses, автоматически генерирующее линзы на основе имен полей записи. *1008*

К сожалению, я имею дело с классами данных без именованных полей, что означает, что 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

1 Ответ

5 голосов
/ 12 января 2020

Field1 имеет стандартную реализацию generi c по умолчанию, так что вы, вероятно, можете добавить экземпляр самостоятельно:

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

data Bar = Bar String deriving (Show, Generic)

instance Field1 Bar Bar String String

generi c -lens также предоставляет те же функциональные возможности, не требуя этого экземпляра шаблона , _1 называется position @1 (из Data.Generics.Product (.Positions) ).

...