Haskell: The Purely Func­tional Pro­gram­ming Lan­guage

Haskell, an open source pro­gram­ming lan­guage, is the out­come of 20 years of re­search. Named af­ter the lo­gi­cian, Haskell Curry, it has all the ad­van­tages of func­tional pro­gram­ming and an in­tu­itive syn­tax based on math­e­mat­i­cal no­ta­tion. This sec­ond ar­ti­cle

OpenSource For You - - DEVELOPERS LET'S TRY -


the func­tion sumInt to com­pute the sum of two in­te­gers. It is de­fined as: sumInt :: Int -> Int -> Int sumInt x y = x + y

The first line is the type sig­na­ture in which the func­tion name, ar­gu­ments and re­turn types are sep­a­rated us­ing a dou­ble colon (::). The ar­gu­ments and the re­turn types are sep­a­rated by the sym­bol (->). Thus, the above type sig­na­ture tells us that the sum func­tion takes two ar­gu­ments of type Int and re­turns an Int. Note that the func­tion names must al­ways be­gin with the let­ters of the al­pha­bet in lower case. The names are usu­ally writ­ten in CamelCase style.

You can cre­ate a Sum.hs Haskell source file us­ing your favourite text edi­tor, and load the file on to the Glas­gow Haskell Com­piler in­ter­preter (GHCi) us­ing the fol­low­ing code: $ ghci GHCi, ver­sion 7.6.3: http://www.haskell.org/ghc/ :? for help Load­ing pack­age ghc-prim ... link­ing ... done. Load­ing pack­age in­te­ger-gmp ... link­ing ... done. Load­ing pack­age base ... link­ing ... done. Pre­lude> :l Sum.hs [1 of 1] Com­pil­ing Main Ok, mod­ules loaded: Main.

( Sum.hs, in­ter­preted ) *Main> :t sumInt sumInt :: Int -> Int -> Int *Main> sumInt 2 3 5

If we check the type of sumInt with ar­gu­ments, we get the fol­low­ing out­put: *Main> :t sumInt 2 3 sumInt 2 3 :: Int

*Main> :t sumInt 2 sumInt 2 :: Int -> Int

The value of sumInt 2 3 is an Int as de­fined in the type sig­na­ture. We can also par­tially ap­ply the func­tion sumInt with one ar­gu­ment and its re­turn type will be Int -> Int. In other words, sumInt 2 takes an in­te­ger and will re­turn an in­te­ger with 2 added to it.

Ev­ery func­tion in Haskell takes only one ar­gu­ment. So, we can think of the sumInt func­tion as one that takes an ar­gu­ment and re­turns a func­tion that takes another ar­gu­ment and com­putes their sum. This re­turn func­tion can be de­fined as a sumT­woInt func­tion that adds a 2 to an Int us­ing the sumInt func­tion, as shown below: sumT­woInt :: Int -> Int sumT­woInt x = sumInt 2 x

The ‘=’ sign in Haskell sig­ni­fies a def­i­ni­tion and not a vari­able as­sign­ment as seen in im­per­a­tive pro­gram­ming lan­guages. We can thus omit the ‘x' on ei­ther side and the code be­comes even more con­cise: sumT­woInt :: Int -> Int sumT­woInt = sumInt 2

By load­ing Sum.hs again in the GHCi prompt, we get the fol­low­ing: *Main> :l Sum.hs [1 of 1] Com­pil­ing Main Ok, mod­ules loaded: Main.

( Sum.hs, in­ter­preted ) *Main> :t sumT­woInt sumT­woInt :: Int -> Int *Main> sumT­woInt 3 5

Let us look at some ex­am­ples of func­tions that op­er­ate on lists. Con­sider list ‘ a', which is de­fined as [ 1, 2, 3, 4, 5] ( a list of in­te­gers) in the Sum.hs file (re-load the file in GHCi be­fore try­ing the list func­tions). a :: [Int] a = [1, 2, 3, 4, 5]

The head func­tion re­turns the first el­e­ment of a list: *Main> head a 1 *Main> :t head head :: [a] -> a

The tail func­tion re­turns ev­ery­thing ex­cept the first el­e­ment

from a list: *Main> tail a [2,3,4,5] *Main> :t tail tail :: [a] -> [a]

The last func­tion re­turns the last el­e­ment of a list: *Main> last a 5 *Main> :t last last :: [a] -> a

The init func­tion re­turns ev­ery­thing ex­cept the last el­e­ment of a list: *Main> init a [1,2,3,4] *Main> :t init init :: [a] -> [a]

The length func­tion re­turns the length of a list: *Main> length a 5 *Main> :t length length :: [a] -> Int

The take func­tion picks the first ‘n' el­e­ments from a list: *Main> take 3 a [1,2,3] *Main> :t take take :: Int -> [a] -> [a]

The drop func­tion drops ‘n' el­e­ments from the begin­ning of a list, and re­turns the rest: *Main> drop 3 a [4,5] *Main> :t drop drop :: Int -> [a] -> [a]

The zip func­tion takes two lists and cre­ates a new list of tu­ples with the re­spec­tive pairs from each list. For ex­am­ple:

*Main> let b = ["one", "two", "three", "four", "five"]

*Main> zip a b [(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five")] *Main> :t zip zip :: [a] -> [b] -> [(a, b)]

The let ex­pres­sion de­fines the value of ‘b' in the GHCi prompt. You can also de­fine it in a way that’s sim­i­lar to the def­i­ni­tion of the list ‘a' in the source file.

The lines func­tion takes in­put text and splits it at new lines:

*Main> let sen­tence = "First\nSe­cond\nThird\nFourth\nFifth" *Main> lines sen­tence ["First","Sec­ond","Third","Fourth","Fifth"] *Main> :t lines lines :: String -> [String]

The words func­tion takes in­put text and splits it on white space: *Main> words "hello world" ["hello","world"] *Main> :t words words :: String -> [String]

The map func­tion takes a func­tion and a list, and ap­plies the func­tion to ev­ery el­e­ment in the list: *Main> map sumT­woInt a [3,4,5,6,7] *Main> :t map map :: (a -> b) -> [a] -> [b]

The first ar­gu­ment to map is a func­tion that is en­closed within paren­the­sis in the type sig­na­ture (a -> b). This func­tion takes an in­put of type ‘a' and re­turns an el­e­ment of type ‘b'. Thus, when op­er­at­ing over a list [a], it re­turns a list of type [b].

Re­cur­sion pro­vides a means of loop­ing in func­tional pro­gram­ming lan­guages. The fac­to­rial of a num­ber, for ex­am­ple, can be com­puted in Haskell, us­ing the fol­low­ing code: fac­to­rial :: Int -> Int fac­to­rial 0 = 1 fac­to­rial n = n * fac­to­rial (n-1)

The def­i­ni­tion of fac­to­rial with dif­fer­ent in­put use cases is called pat­tern match­ing on the func­tion. On run­ning the above ex­am­ple with GHCi, you get the fol­low­ing out­put:

*Main> fac­to­rial 0 1 *Main> fac­to­rial 1 1 *Main> fac­to­rial 2 2 *Main> fac­to­rial 3 6 *Main> fac­to­rial 4 24 *Main> fac­to­rial 5 120

Func­tions op­er­at­ing on lists can also be called re­cur­sively. To com­pute the sum of a list of in­te­gers, you can write the sumList func­tion as: sumList :: [Int] -> Int sumList [] = 0 sumList (x:xs) = x + sumList xs

The no­ta­tion (x:xs) rep­re­sents a list, where ‘x' is the first el­e­ment in the list and ‘xs' is the rest of the list. On run­ning sumList with GHCi, you get the fol­low­ing: *Main> sumList [] 0 *Main> sumList [1,2,3] 6

Some­times, you will need a tem­po­rary func­tion for a com­pu­ta­tion, which you will not need to use else­where. You can then write an anony­mous func­tion. A func­tion to in­cre­ment an in­put value can be de­fined as: *Main> (\x -> x + 1) 3 4

These are called Lambda func­tions, and the '\' rep­re­sents the no­ta­tion for the sym­bol Lambda. Another ex­am­ple is given below: *Main> map (\x -> x * x) [1, 2, 3, 4, 5] [1,4,9,16,25]

It is a good prac­tice to write the type sig­na­ture of the func­tion first when com­pos­ing pro­grams, and then write the body of the func­tion. Haskell is a func­tional pro­gram­ming lan­guage and un­der­stand­ing the use of func­tions is very im­por­tant.

Newspapers in English

Newspapers from India

© PressReader. All rights reserved.