Может ли поле записи быть сопоставлено с некоторым значением и назначено параметру одновременно?
После относительно короткого текста в Haskell wiki о сопоставлении шаблонов записей, я не уверен, что поле записи может быть сопоставлено с некоторым значением и назначено параметру в то же время.
-- Sample record type
data Rec = Rec { uid :: Int, name :: String }
-- Function to update Rec 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 [email protected]"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 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 [email protected](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 = ...
Итак, существует ли какой-то краткий способ сопоставления шаблонов по полю записи и назначать его значение одновременно?
Примечание. Я хотел бы избежать конкретных расширений GHC.
Ответы
Ответ 1
Имена полей - это сами шаблоны, поэтому вы можете использовать другой шаблон as-pattern:
updateRec Rec {name = [email protected]"Bob", uid = [email protected]} = ...
Существует не более сжатый способ сделать это, стандартный или с расширениями GHC. Конечно, для такого простого случая вы можете просто опустить привязки и использовать "Bob"
и 42
непосредственно в теле функции.