Safe Haskell | None |
---|
Flexible records with named fields.
Named records allow you to define und use records with labeled fields. These records are first class objects. Record fields are labeled by names, which can basically be any type. However, the names package provides global name types and some syntactic sugar to use them.
Here is a complete walk-through, with Template Haskell syntactic sugar.
This is how a typical example preamble looks like:
import qualified Data.Name import Data.NamedRecord
In order to use names you need to declare them first
(see the names
package for further details):
name "firstName" name "lastName"
These are two records Person
and User
:
record "Person" `has` "firstName" := ''String `has` "lastName" := ''String record "User" `has` "firstName" := ''String `has` "lastName" := ''String `has` "loginName" := ''String
Note that these declarations create constructor
functions newPerson
and newUser
, as well as
type synonyms Person
and User
(use -ddump-splices
to see what has been generated).
Here are two instances of these recors:
julian = newPerson `set` firstName := "Julian" `set` lastName := "Fleischer" alexander = newUser `set` firstName := "Alexander" `set` lastName := "Carnicero" `set` loginName := "alexander.carnicero"
We can now create a displayName
function like
the following:
displayName obj = (obj `get` firstName) ++ " " ++ (obj `get` lastName)
Note that this function will accept any record
that has a firstName
and a lastName
field of
type String
.
>>>
displayName julian
Julian Fleischer
>>>
displayName alexander
Alexander Carnicero
As mentioned above, records are first class citizens. That means you can create them anywhere:
>>>
displayName (firstName := "John" :+ lastName := "Doe")
John Doe
It is also possible to declare default values:
name "serverName" name "port" record "ServerConfig" `has` "serverName" := ''String := "localhost" `has` "port" := ''Int := (4711 :: Int)
>>>
newServerConfig
serverName := "localhost" :+ port := 4711
>>>
newServerConfig `set` serverName := "example.org"
serverName := "example.org" :+ port := 4711
>>>
newServerConfig `get` port
4711
Complex expressions and types need to be quoted using
[e| expr |]
and [t| type |]
like so:
record "Server" `has` "requestHandler" := [t| Request -> Response |] := [e| \x -> answer x |] `has` "config" := ''Config := [e| newConfig |]
- class Property o n v | o n -> v where
- add :: b -> a -> a :+ b
- data a := b = a := b
- data a :+ b = a :+ b
- record :: String -> Record
- has :: RecordTemplate a b c => a -> b -> c
- class RecordTemplate a b c | a b -> c where
- (~>) :: a -> b -> c
- name :: String -> Q [Dec]
- nameT :: String -> Q Type
- nameV :: String -> Q Exp
Documentation
a := b |
(Show a, Show b) => Show (:= a b) | |
Property (:+ (:= n v) b) n v | |
Property (:= n v) n v | |
ToType v => RecordTemplate (:= String v) [(String, Q Type, Maybe (Q Exp))] [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToExp d) => RecordTemplate (:= (:= String v) d) [(String, Q Type, Maybe (Q Exp))] [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w, ToExp e) => RecordTemplate (:= String v) (:= (:= String w) e) [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w) => RecordTemplate (:= String v) (:= String w) [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w, ToExp d, ToExp e) => RecordTemplate (:= (:= String v) d) (:= (:= String w) e) [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w, ToExp d) => RecordTemplate (:= (:= String v) d) (:= String w) [(String, Q Type, Maybe (Q Exp))] |
a :+ b |
Template Haskell Syntactic Sugar
Declares a record (looks like a new keyword record
).
See the examples.
Declares a field of a record. Use as infix operators. See the examples.
has :: RecordTemplate a b c => a -> b -> cSource
class RecordTemplate a b c | a b -> c whereSource
ToType v => RecordTemplate (:= String v) [(String, Q Type, Maybe (Q Exp))] [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToExp d) => RecordTemplate (:= (:= String v) d) [(String, Q Type, Maybe (Q Exp))] [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w, ToExp e) => RecordTemplate (:= String v) (:= (:= String w) e) [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w) => RecordTemplate (:= String v) (:= String w) [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w, ToExp d, ToExp e) => RecordTemplate (:= (:= String v) d) (:= (:= String w) e) [(String, Q Type, Maybe (Q Exp))] | |
(ToType v, ToType w, ToExp d) => RecordTemplate (:= (:= String v) d) (:= String w) [(String, Q Type, Maybe (Q Exp))] |