I want to update a record using lens with a value parsed by attoparsec.
fmap (myRecord & _2 . someField .~) double
And it totally doesn't work:
Iddq3.hs:99:48:
The operator ‘.~’ [infixr 4] of a section
must have lower precedence than that of the operand,
namely ‘&’ [infixl 1]
in the section: ‘myRecord & _2 . someField .~’
What does this error mean? What are infixr
and infixl
? How can I rewrite the function to correct it?
You just can't mix operators of that fixity. Fixity in Haskell is just operator precedence, just like your "Please Excuse My Dear Aunt Sally" (if you're American, this is probably what you learned) for remembering what order to apply operations in, i.e. Parentheses, Exponent, Multiplication, Division, Addition, Subtraction. Here, the .~
operator is said to have a higher right associative precedence than the left associative low precedence of the &
operator. The real problem comes from mixing the right and left associative operators, the compiler doesn't know what order to apply them in!
Instead, you can re-formulate it as two operator sections composed together
fmap ((myRecord &) . (_2 . someField .~)) double
So that you give the compiler an explicit grouping, or you can use the prefix set
function for a cleaner look
fmap (\v -> set (_2 . someField) v myRecord) double
Or if you want to get rid of the lambda (my preference is to leave it alone), you can use flip
as
fmap (flip (set (_2 . someField)) myRecord) double