Reputation: 1527
I have defined a data type called Name which consists of the type synonyms FirstName and LastName.
How would I print out the first name? I understand how to do it in record syntax but not in the default syntax.
type FirstName = String
type LastName = String
data Name = Name FirstName LastName
main = do
tim <- Name "tim" "lim"
putStrLn (FirstName tim)
I get the following error:
test.hs:11:17: error:
Data constructor not in scope: FirstName :: t0 -> String
|
11 | putStrLn (FirstName tim)
| ^^^^^^^^^
Upvotes: 2
Views: 921
Reputation: 477180
You unpack it, for example with pattern matching:
type FirstName = String
type LastName = String
data Name = Name FirstName LastName
main = do
let Name fn _ = Name "tim" "lim"
putStrLn fn
But it might be better to use a record for your Name
:
data Name = Name { firstName :: FirstName, lastName :: LastName }
Then Haskell will automatically generate two functions firstName :: Name -> FirstName
and lastName :: Name -> LastName
, so you can then use that function with:
main = do
let tim = Name "tim" "lim"
putStrLn (firstName tim)
The main advantage of using record syntax is that you can easily obtain a field from a data constructor, without having to unpack the data constructor, and taking care of all the fields. If the amount of fields grows, it would likely take some extra work to refactor all places where you used the non-record syntax in the first place.
Note: you can not use syntax like
tim <- Name "tim" "lim"
here, sinceName
is not a function that returns a monadic value).
Upvotes: 3
Reputation: 3857
If you haven't define a record visitor, then the only way to visit it's field is pattern matching:
type FirstName = String
type LastName = String
data Name = Name FirstName LastName
main = do
let tim = Name "tim" "lim"
putStrLn (case tim of Name fname lname -> fname)
Upvotes: 2