Haskell dynamically set record field based on field name string?

后端 未结 2 1961
你的背包
你的背包 2020-12-09 12:27

Say I have the following record:

data Rec = Rec {
   field1 :: Int,
   field2 :: Int
}

How do I write the function:

changeF         


        
2条回答
  •  旧巷少年郎
    2020-12-09 12:49

    You can build a map from the field names to their lenses:

    {-# LANGUAGE TemplateHaskell #-}
    import Data.Lens
    import Data.Lens.Template
    import qualified Data.Map as Map
    
    data Rec = Rec {
        _field1 :: Int,
        _field2 :: Int
    } deriving(Show)
    
    $( makeLens ''Rec )
    
    recMap = Map.fromList [ ("field1", field1)
                          , ("field2", field2)
                          ]
    
    changeField :: Rec -> String -> Int -> Rec
    changeField rec fieldName value = set rec
        where set = (recMap Map.! fieldName) ^= value
    
    main = do
      let r = Rec { _field1 = 1, _field2 = 2 }
      print r
      let r' = changeField r "field1" 10
      let r'' = changeField r' "field2" 20
      print r''
    

    or without lenses:

    import qualified Data.Map as Map
    
    data Rec = Rec {
        field1 :: Int,
        field2 :: Int
    } deriving(Show)
    
    recMap = Map.fromList [ ("field1", \r v -> r { field1 = v })
                          , ("field2", \r v -> r { field2 = v })
                          ]
    
    changeField :: Rec -> String -> Int -> Rec
    changeField rec fieldName value =
        (recMap Map.! fieldName) rec value
    
    main = do
      let r = Rec { field1 = 1, field2 = 2 }
      print r
      let r' = changeField r "field1" 10
      let r'' = changeField r' "field2" 20
      print r''
    

提交回复
热议问题