After a relatively brief text on Haskell wiki about pattern matching of records, I'm not sure if record's field can be matched with some value and assigned to a parameter at the same time.
-- Sample record type
data Rec = Rec { uid :: Int, name :: String }
-- Function to update Rec's fields
updateRec :: Rec -> Rec
-- basic matching with record data constructor
updateRec (Rec _ []) = Rec 0 "Nobody"
-- dtto with as-pattern at 2nd param
updateRec (Rec idn ns@"Alice") = Rec (idn+1) (ns ++ "+1")
-- basic matching by fields values
updateRec Rec {name = "Bob", uid = 42} = Rec (10^6) "SuperBob"
-- Q: how to match by name field and assign it's value ?
updateRec Rec {name = "Bob", uid = idn} =
Rec {uid = (idn+1), name = ("Bob" ++ "+1")}
-- Q: as-pattern works only on the whole record, not on a field
updateRec rec@(Rec {name = "Bob", uid = idn}) =
Rec {uid = (idn+1), name = (name rec ++ "+1")}
-- Q: pattern guards do work, but they are a bit clumsy
updateRec Rec {name = uname, uid = idn}
| uname == "Bob" = Rec {uid = (idn+1), name = (uname ++ "+1")}
| otherwise = ...
So is there some concise way to pattern match by record's field and assign its value at the same time?
Note: I would like to avoid specific GHC's extensions.
The field names are patterns themselves, so you can use another as-pattern:
updateRec Rec {name = uname@"Bob", uid = idn@42} = ...
There isn't any more concise way to do this, standard or with GHC extensions. Of course, for a case as simple as this, you could simply omit the bindings and use "Bob"
and 42
directly in the function body.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With