How can I briefly change the record field?

data Person = Person
  {
    name :: String
  , counter :: Int
  }

incrementPersonCounter :: Person -> Person
incrementPersonCounter p@(Person _ c) = p { counter = c + 1 }

Is there a more concise way to do this? Is there a function that I could use where I specify the record, one of its fields ( name/ counterin this case) and a function to apply to the return value?


I thought something like:

applyRecord r f f' = r
  { f = f' (f r) }

Although this will not work, because:

error: Not in scope: ‘f’
   |
13 |   { f = f' (f r) }
+4
source share
2 answers

One way to generalize incrementPersonCounteris the abstract over the modification function:

modifyPersonCounter :: (Int -> Int) -> Person -> Person
modifyPersonCounter f p = (\c -> p { counter = c}) $ f (counter p)

In fact, the general template is an abstraction, as well as the effect that we want to perform in the field:

counterLens :: forall f. Functor f => (Int -> f Int) -> (Person -> f Person)
counterLens f p = (\c -> p { counter = c }) <$> f (counter p)

For example, we may need to read the counter increment from the console or from the database (both effects IO).

, , ( ) , :

type Lens' a b = forall f. Functor f => (b -> f b) -> (a -> f a)

, , over, :

over :: Lens' a b -> (b -> b) -> a -> a
over l f p = runIdentity $ l (Identity . f) p

:

*Main> over counterLens (+1) (Person "foo" 40)
Person {name = "foo", counter = 41}

, "" , . Template Haskell, .

, , ? , , . , , . , ( , Haskell ), , , .

lens, microlens, . : , , .

+7

lens, :

incrementPersonCounter :: Person -> Person
incrementPersonCounter = counter +~ 1

:

λ> incrementPersonCounter $ Person "foo" 42
Person {_name = "foo", _counter = 43}

:

{-# LANGUAGE TemplateHaskell #-}

module Lib where

import Control.Lens

data Person = Person
  {
    _name :: String
  , _counter :: Int
  } deriving (Show, Eq)
makeLenses ''Person

incrementPersonCounter :: Person -> Person
incrementPersonCounter = counter +~ 1
+4

Source: https://habr.com/ru/post/1690480/


All Articles