La sintassi della registrazione sembra estremamente comoda rispetto alla necessità di scrivere le proprie funzioni di accesso. Non ho mai visto nessuno dare delle linee guida su quando è meglio usare la sintassi del record sulla normale sintassi della dichiarazione dei dati, quindi mi limiterò a chiedere qui.Quando dovrei usare la sintassi del record per le dichiarazioni di dati in Haskell?
risposta
Si dovrebbe usare la sintassi di registrazione in due situazioni:
- Il tipo ha molti campi
- La dichiarazione del tipo dà alcun indizio circa il suo layout destinato
Per esempio un tipo di punto può essere semplicemente dichiarato come:
data Point = Point Int Int deriving (Show)
È ovvio che il primo t indica la coordinata x e la seconda sta per y. Ma il caso con la seguente dichiarazione di tipo diverso (tratto da Learn You a Haskell for Great Good):
data Person = Person String String Int Float String String deriving (Show)
Il layout tipo previsto è: nome, cognome, età, altezza, numero di telefono, e favorito il sapore di gelato. Ma questo non è evidente nella dichiarazione di cui sopra. sintassi Record viene portata di mano qui:
data Person = Person { firstName :: String
, lastName :: String
, age :: Int
, height :: Float
, phoneNumber :: String
, flavor :: String
} deriving (Show)
La sintassi verbale reso il codice più leggibile, e salvato una grande quantità di battitura definendo automaticamente tutte le funzioni di accesso per noi!
Oltre ai dati complessi a più campi, i valori di newtype
vengono spesso definiti con la sintassi del record. In nessuno di questi casi, non ci sono davvero dei lati negativi nell'usare la sintassi dei record, ma nel caso dei tipi di somma, i metodi di accesso ai record di solito non hanno senso. Ad esempio:
data Either a b = Left { getLeft :: a } | Right { getRight :: b }
è valido, ma le funzioni di accesso sono parziale - è un errore di scrivere getLeft (Right "banana")
. Per questo motivo, tali utenti sono generalmente scoraggiati; qualcosa come getLeft :: Either a b -> Maybe a
sarebbe più comune e dovrebbe essere definito manualmente. Si noti tuttavia che di accesso possono condividere nomi:
data Item = Food { description :: String, tastiness :: Integer }
| Wand { description :: String, magic :: Integer }
Ora description
è totale, anche se tastiness
e magic
entrambi ancora non lo sono.
Hai anche un uso interessante della sintassi del record nella monade 'State', dove' runState' è usato come un po 'di intelligenza sintattica. – jberryman
Si potrebbe sfruttare il sistema dei tipi e l'uso di tipo aliasing come 'tipo FirstName = Stringa Tipo Cognome = Stringa tipo Età = Int tipo Altezza = Float tipo PhoneNumber = Stringa tipo Sapore = Stringa persona dati = persona FirstName LastName Età Altezza PhoneNumber Sapore derivante (mostra) ' Pertanto il tuo argomento non è valido. – yaccz