Can I force the use of keywords only when initializing a record in Haskell?
data Person
= Person
{
name :: String,
idnum :: String
}
deriving( Show )
main = putStrLn $ show $ Person "oren" "9200"
-- I want to only allow such initializations:
-- main = putStrLn $ show $ Person { name = "moish", idnum = "7400" }
(This is especially useful when two fields have the same type)
CodePudding user response:
As far as I know, no.
Consider maybe the following solution?
newtype Name = Name String
newtype Idnum = Idnum String
data Person = Person { name :: Name, idnum :: Idnum }
Another possibility, worse in my opinion, is this:
module A (Person, name, idnum) where
data Person = Person
{ _name :: String
, _idnum :: String
}
name :: String -> (Person -> Person)
name n p = p { _name = n }
idnum :: String -> (Person -> Person)
idnum n p = p { _idnum = n }
emptyPerson :: Person
emptyPerson = Person "" ""
# in another module
module B
import A (Person, name, idnum)
myPerson = name "myname" . idnum "myidnum" $ emptyPerson
In this case there's no guarantee that both name
and idnum
get a value.
The fact that Person
can always be used as a 'plain function' may turn out to be very useful. If you have, for instance, getName :: IO String
and getIdnum :: IO String
, then combining these to form a getPerson :: IO Person
is concise: getPerson = Person <$> getName <*> getIdnum
. This is only possible because we don't use record syntax here!