In my previous posts, I explained about
custom types, pattern matching against custom types. Let me briefly explain
with an example.
BooksUtil.hs
type ISBN = String type Title = String type Authors = [String] data BookInfo = Book ISBN Title Authors getIsbn :: BookInfo -> ISBN getIsbn (Book isbn _ _) = isbn getTitle :: BookInfo -> Title getTitle (Book _ title _) = title getAuthors :: BookInfo -> Authors getAuthors (Book _ _ authors) = authors
*Main> :load BookUtil.hs [1 of 1] Compiling Main ( BookUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> let bk1 = Book "123SVC" "Java Tutorial" ["Krishna", "Hari"] *Main> *Main> getIsbn bk1 "123SVC" *Main> *Main> getTitle bk1 "Java Tutorial" *Main> *Main> getAuthors bk1 ["Krishna","Hari"] *Main>
Observe BookUtil.hs, i had written three
functions getIsbn, getTitle, getAuthors to extract ISBN, Title, Authors
information respectively. Observe the above code, we are repeating the same
logic in all the three functions. We can remove this kind of boilerplate code
by using the record syntax notation.
We can redefine our custom type BookInfo
using record syntax like below.
data BookInfo = Book { isbn :: ISBN, title :: Title, authors :: Authors } deriving (Show)
Following
statement creates a variable of type Book.
bk1 = Book
"123SVC" "Java Tutorial" ["Krishna",
"Hari"]
'isbn bk1'
return ISBN number of book bk1.
'title bk1'
return the title of book bk1.
'authors bk1'
return the authors of book bk1.
Following is
the complete working application.
BookUtil.hs
type ISBN = String type Title = String type Authors = [String] data BookInfo = Book { isbn :: ISBN, title :: Title, authors :: Authors } deriving (Show)
Above definition automatically generate
the following accessor functions for us.
isbn :: BookInfo -> ISBN title :: BookInfo -> Title authors :: BookInfo -> Authors
*Main> :load BookUtil.hs [1 of 1] Compiling Main ( BookUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> let bk1 = Book "123SVC" "Java Tutorial" ["Krishna", "Hari"] *Main> *Main> bk1 Book {isbn = "123SVC", title = "Java Tutorial", authors = ["Krishna","Hari"]} *Main> *Main> isbn bk1 "123SVC" *Main> *Main> title bk1 "Java Tutorial" *Main> *Main> authors bk1 ["Krishna","Hari"] *Main>
You can also
create an instance of Book like below.
bk1 = Book{title="Java Tutorial", authors=["Hari", "Krishna"], isbn="ISBN12345"}
One advantage of above notation is, we
no need to remember the order of fields in the custom data type.
*Main> let bk1 = Book{title="Java Tutorial", authors=["Hari", "Krishna"], isbn="ISBN12345"} *Main> *Main> title bk1 "Java Tutorial" *Main> *Main> isbn bk1 "ISBN12345" *Main> *Main> authors bk1 ["Hari","Krishna"] *Main>
When you define a type signature using the
record syntax, it changes the way that type values are printed.
*Main> let bk1 = Book{title="Java Tutorial", authors=["Hari", "Krishna"], isbn="ISBN12345"} *Main> bk1 Book {isbn = "ISBN12345", title = "Java Tutorial", authors = ["Hari","Krishna"]}
One more advantage of record notation
is, you can update the fields of a type conveniently.
bk1 = Book{title="Java Tutorial", authors=["Hari", "Krishna"], isbn="ISBN12345"} bk2 = bk1 {title = "Haskell Tutorial"}
bk2 has the title "Haskell
Tutorial", and maintain remaining properties same as bk1.
*Main> let bk1 = Book{title="Java Tutorial", authors=["Hari", "Krishna"], isbn="ISBN12345"} *Main> *Main> let bk2 = bk1 {title = "Haskell Tutorial"} *Main> bk2 Book {isbn = "ISBN12345", title = "Haskell Tutorial", authors = ["Hari","Krishna"]}
So, in general, to update the field x in
a datatype y to z, you write y { x = z }.
You can perform updates on multiple
fields at a time by separating them using commas.
*Main> let bk3 = bk1 {title = "Python Tutorial", isbn = "ISBN3245"} *Main> bk3 Book {isbn = "ISBN3245", title = "Python Tutorial", authors = ["Hari","Krishna"]}
You can apply
pattern matching against named fields in record notations.
getInfo (Book
{isbn = is, title = ti}) = (is, ti)
Above function
matches isbn field to the variable is, title field to the variable ti.
BookUtil.hs
type ISBN = String type Title = String type Authors = [String] data BookInfo = Book { isbn :: ISBN, title :: Title, authors :: Authors } deriving (Show) getInfo (Book {isbn = is, title = ti}) = (is, ti)
*Main> :load BookUtil.hs [1 of 1] Compiling Main ( BookUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> let bk1 = Book{title="Java Tutorial", authors=["Hari", "Krishna"], isbn="ISBN12345"} *Main> getInfo bk1 ("ISBN12345","Java Tutorial")
No comments:
Post a Comment