As per its documentation, Haskell's lens
library's _1
provides a lens for tuples.
For data records, there are instead several other functions such as makeLenses
, automatically generating lenses based on the record's field names.
Unfortunately, I am dealing with data classes without named fields, meaning makeLenses
appears out for me.
This makes me wonder. _1
seems quite convenient, yet as implied in its documentation, appears not to work on data classes. Is there an equivalent of a similar level of convenience?
> :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
Adding the FlexibleContexts
extension, I instead face another error:
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
has a default generic implementation, so you can probably add an instance yourself:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)
data Bar = Bar String deriving (Show, Generic)
instance Field1 Bar Bar String String
generic-lens also provides the same functionality, without requiring that boilerplate instance. _1
is called position @1
(from Data.Generics.Product
(.Positions
)).