timothyylim
timothyylim

Reputation: 1527

Access data property [Haskell]

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

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

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, since Name is not a function that returns a monadic value).

Upvotes: 3

luochen1990
luochen1990

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

Related Questions