G TTT
G TTT

Reputation: 37

Iterating over a custom type and access the property inside in haskell

I have custom type below:

-- (Int,Int,Int) = (Year, Month, Day)
type Birth = (Int, Int, Int)
type Book = String
data Author = Author Book Book Book Birth

I was thinking that (Q1) if there is a way to iterate over the property inside Author, which means a function fun applied to a Author type will return Book values separately. I have thought using

BookA :: Author -> Book
BookA (Author bkA _ _ _) = bkA

or case...ofstatement to get all three books separately, but it is too redundant. Is there a way iterately or recursively?

Also, (Q2) how can I get the BirthDay in a single function insdead of these:

birth :: Author -> Birth
birth (Author _ _ _ birth) = birth

bDay :: Birth -> Int
bDay (_,_,bDay) = bDay

Thank you guys so much.

Upvotes: 1

Views: 203

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477606

I was thinking that (Q1) if there is a way to iterate over the property inside Author (…)

Although you can do that with Data, it here looks a bit overkill. You can here simply match the tree books, and return these in a list:

BookA :: Author -> [Book]
BookA (Author bkA bkB bkC _) = [bkA, bkB, bkC]

Here it makes more sense however to define a list of Books for an Author, since now you basically say that each Author has written exactly three books. By making a list, an Author can have written, zero, one, or more books:

data Author = Author [Book] Birth

You can even use records syntax, and let Haskell write the getters for you:

data Author = Author { booksA :: [Book], birth :: Birth }

Also, (Q2) how can I get the BirthDay in a single function insdead of these (…)

You can use nested patterns, like:

bday :: Author -> Birth
bdayA (Author _ _ _ (_, _, bd)) = bd

But often in Haskell one makes small reusable functions that can be combined. If you thus define birth and bDay, like you did, you can define the birthday of an Author with:

birth :: Author -> Birth
birth (Author _ _ _ birth) = birth

bDay :: Birth -> Int
bDay (_,_,bDay) = bDay

bDayA :: Author -> Int
bDayA = bDay . birth

Upvotes: 2

Fyodor Soikin
Fyodor Soikin

Reputation: 80890

Q1: You can get all three books at the same time by pattern matching, and then return them as a list:

books :: Author -> [Book]
books (Author a b c _) = [a, b, c]

But are you sure you want to define your Author like that? What if an author has two books or four? Such author wouldn't fit your definition, would it?

As @WillemVanOnsem pointed out in the comments, a more robust definition would be to make Author contain a list of Book instead of three books separately:

data Author = Author [Book] Birth

Q2: You can compose the two functions you have:

authorBDay :: Author -> Int
authorBDay = bDay . birth

Or, alternatively, you can pattern match directly:

authorBDay :: Author -> Int
authorBDay (Author _ _ _ (_,_,d)) = d

Patterns can be nested. That's their primary point.

Upvotes: 3

Related Questions