2012-01-30 6 views
23

Después de un texto relativamente breve en la wiki de Haskell sobre la coincidencia de patrones de registros, no estoy seguro de si el campo del registro puede coincidir con algún valor y asignarse a un parámetro al mismo tiempo.¿Puede coincidir el campo de registro con algún valor y asignarse a un parámetro al mismo tiempo?

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

Entonces, ¿hay alguna manera concisa modelar el partido por el campo de registro y asignar su valor al mismo tiempo?

Nota: Me gustaría evitar las extensiones de GHC específicas.

Respuesta

29

Los nombres de campo son los patrones de sí mismos, por lo que puede utilizar otro como patrón:

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

no hay ninguna forma más concisa para hacer esto, extensiones estándar o con GHC. Por supuesto, para un caso tan simple como este, simplemente podría omitir los enlaces y usar "Bob" y 42 directamente en el cuerpo de la función.

Cuestiones relacionadas