2012-01-30 16 views
23

Sau một văn bản tương đối ngắn trên Haskell wiki về mẫu khớp của bản ghi, tôi không chắc liệu trường của bản ghi có thể được khớp với một số giá trị và được gán cho tham số cùng một lúc hay không.Trường của bản ghi có thể khớp với một số giá trị và được gán cho tham số cùng một lúc không?

-- 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 [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'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 [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 = ... 

Vì vậy, có một số cách ngắn gọn để khớp mẫu theo trường của bản ghi và gán giá trị của nó cùng một lúc?

Lưu ý: Tôi muốn tránh các phần mở rộng cụ thể của GHC.

Trả lời

29

Các tên trường là mẫu thân, vì vậy bạn có thể sử dụng một như-pattern:

updateRec Rec {name = [email protected]"Bob", uid = [email protected]} = ... 

Không có bất kỳ cách ngắn gọn hơn để làm điều này, tiêu chuẩn hoặc có phần mở rộng GHC. Tất nhiên, đối với một trường hợp đơn giản như thế này, bạn có thể chỉ cần bỏ qua các ràng buộc và sử dụng "Bob"42 trực tiếp trong phần thân hàm.

Các vấn đề liên quan