Top Banner

of 44

Haskell Tutorial for C Programmers

Jun 03, 2018

Download

Documents

g_teodorescu
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • 8/12/2019 Haskell Tutorial for C Programmers

    1/44

    Haskell Tutorial for C Programmers

    Haskell Tutorial for C Programmers, by Eric Etheridge

    version 3.0 - lease increment !ith ma"or udatesoriginal author# Eric Etheridgelast ma"or udate by the original author# $ugust %&, %0''year of original release (on old haskell.org site)# %00*

    Contents

    +hide ' ntroduction

    o '.' $bstract

    o '.% o!nloadso '.3 /icense

    o '. This Tutorial1s Purose and 2ther 2nline eferences

    '..' 4HC and Hugs '..% The 4entle ntroduction to Haskell

    '..3 Tour of the Haskell 5ynta6 '.. The Prelude 7ile

    '..* 4HC Heirarchical /ibraries '..8 9onads for the :orking Haskell Programmer

    o '.* Preface and 5tyle ;otes

    % 5ection # :hat the Heck is 4oing 2nut eally a 5idetrack to Tyes

    o 3.3 Part # 9ore Tyes, >ecause Haskell s 1Polymorhic1

    o 3. Part =# 7unctions $lready

    5ection # ;o! /et1s eally :rite 7unctionso .' Part # id @ou Take That >reak< Here $re Patterns

    o .% Part # $fter Patterns, 4uards

    o .3 Part # 1f1

    o . Part =# ndention 5ynta6

    o .* Part =# $nd /ambda 7unctions

    o .8 Part =# Polymorhic Tyes and Tye Constructors

    o .A Part =# The 2 9onad

    o .& Part =# issecting the 2 E6amle

    * 5ection =# Haskell and @ou

    o *.' Part # :here $re the 17or1 /oosecause of this, use some difficult roblemsin this tutorial. on1t !orry if you don1t understand the solutions after reading the tutorialonce. Haskell is not a toy language, and even a moderately si?ed set of functions !ill includeseveral of Haskell1s comlicated tools all !orking together. This has left educators !ith adilemma# do use ridiculously simle code in order to cover a single toic at once, or do usesomething actually useful and try to e6lain all the ieces and ho! they all fit together< 9anytutorials and lessons have chosen the former, but refer the latter. That means that each

    e6amle reIuires a lot of e6laining. 2ften concets must be e6lained once in e6tremelysimlistic terms, and then e6lained again later after other related toics have also been

    briefly discussed. $s you read this tutorial, remember this# Haskell1s real o!er is the factthat all of its ieces fit so !ell together, not "ust that they are good ieces.

    The synta6 and variable name conventions use in this tutorial are those used in the Haskellsource code and libraries, and !hat learned in college. Haskell rograms tend to be short,

    but !ide. recommend using descritive variable names, even for indices and so forth.

    2 'ection I0 !at t!e Heck is &oing $n

    http://www.haskell.org/ghc/docs/latest/html/libraries/index.htmlhttp://www.haskell.org/ghc/docs/latest/html/libraries/index.htmlhttp://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htmhttp://www.haskell.org/ghc/docs/latest/html/libraries/index.htmlhttp://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm
  • 8/12/2019 Haskell Tutorial for C Programmers

    6/44

    2.1 Part I0 Haskell"s $ddit(

    To begin, Haskell has no udate oerator. f that sentence did not make sense, then leasekee reading, because this tutorial !as !ritten !ith you in mind. >y 1udate oerator1, meanthat the follo!ing does not haen in normal Haskell#

    int aa := 4print aa := 5print a

    > 4> 5

    The above rogramming style, i.e. 1making a variable, utting data in it, using it, thenrelacing the data in it, using it again1 does not haen in normal Haskell. Those of you !ho

    have used /5P or 5cheme !ill be familiar !ith this concet, but am sure that the rest ofyou are robably baffled. Here is ho! Haskell !orks, again in seudo-code#

    print a

    int aa = 5

    > 5

    or

    int aa = 5

    print a

    > 5

    The order of these actions does not matter. There is also a reason that the first e6amle used1#O1 and the second e6amle used 1O1. n 1imerative1 languages, storing data is an oeration,and it haens in a seIuence. n 1functional1 languages like Haskell, the eIual sign means ane6act definition. n other !ords, each variable is eIual to its value not only after theassignment statement is reached in seIuence, but in fact at all oints during e6ecution.

    5ome of you may be saying, GThat1s nice, Eric, but !hat good is a language !here everythingis hardcoded< :ouldn1t have to define every variable !ith its correct value as coded< sn1t1comuting1 values the !hole oint of a 1comuter1

  • 8/12/2019 Haskell Tutorial for C Programmers

    7/44

    int result;result = bar * 10 + 4;return result;

    }

    The imortant art is the e6ression in the middle. t can also be !ritten as follo!s#

    int foo (int bar) {return bar * 10 + 4;

    }

    These are the same, but the second is shorter and clearer. :ith a function like this, you couldstate the follo!ing# GThe value of foo(6) is eIual to (6 Q '0 D ).G 2r, more simly, Gfoo(6) O6 Q '0 D G. kno! you1re saying, G9ost functions aren1t that simle.G That is true, but bear!ith me. Haskell has much more o!erful tools for !riting functions than most otherlanguages, and a lot of comlicated oerations look this simle in Haskell. The key to usingthose tools !ill be changing the !ay you think from "make data t!en alter it"to "define a

    function t!at would return t!e result t!en a##l( to in#uts".

    2.2 Part II0 In#ut and $ut#ut

    :e1ll come back to the frame of mind later. There is such a difference bet!een Haskell andCFCDD that many concets only make sense in con"unction !ith others. need to cover the

    basics of several concets before can e6lain each of them fully.

    9oving on, the Iuestion on everybody1s mind is robably either, GHo! does F2 !ork

  • 8/12/2019 Haskell Tutorial for C Programmers

    8/44

    2.3 Part III0 er( 4asic Intro to T(#es

    9oving on again, let1s talk about tools. Haskell1s greatest strength lies in the o!er arogrammer has to define useful functions easily and clearly. Here is our earlier e6amlefrom C#

    int foo (int bar) {return bar * 10 + 4;

    }

    n Haskell, to !rite this function named foo, you !ould !rite the follo!ing#

    foo bar = bar * 10 + 4

    That1s all, e6cet for the tye#

    foo :: Int -> Int

    The tye reads, Gfoo is of tye nt to ntG, meaning that it takes an nt and returns an nt.Together, you !rite#

    foo :: Int -> Intfoo bar = bar * 10 + 4

    efining functions and tyes is the ma"ority of the !ork in Haskell, and usually they reIuireeIual amounts of time. Haskell has a variety of !ays to define functions. feel that thetutorials mentioned reviously do not adeIuately introduce these !ays, so !e !ill discussthem in detail later once !e have some tools under our belt.

    2. Part I0 Haskell"s Lists and List Com#re!ensions

    Those of you familiar !ith C kno! that ointers are the rimary ob"ect in the language. 7oralmost all imerative languages, the most useful structure is the $rray, a randomly accessibleseIuence of values usually stored in order in memory. Haskell has arrays, but the most-usedob"ect in Haskell is a /ist. $ list in Haskell is accessible only at the front, and is not stored inorder in memory. :hile this may sound atrocious, Haskell has such !eird abilities that it is

    more natural to use a list than an array, and often faster. /et us start !ith the C code tocomute the fibonacci numbers (starting !ith ?ero)#

    int fib (int n) {int a = 0, b = 1, i, tep;for (i = 0; i ! n; i++) {

    tep = a + b;a = b;b = tep;

    }return a;

    }

  • 8/12/2019 Haskell Tutorial for C Programmers

    9/44

    This is fine for comuting a articular value, but things get ugly !hen you !ant to create theseIuence#

    int * fib"rra#(int n) {int * fibs;fibs = (int *)allo$((si%eof int) * n);for (i = 0; i ! n; i++) {

    fibs&i' = a;tep = a + b;a = b;b = tep;

    }return fibs;

    }

    :hen say 1get ugly1, mean that something is included in that function !hich shouldn1t bethere# the si?e of the list. The fibonacci seIuence is infinite, and the code above does notreresent it, only a art of it. This doesn1t sound so bad, unless you don1t kno! ho! many

    values you need initially.

    n Haskell, 1fib1, the function to comute a single fibonacci value, can be !ritten as follo!s#

    fib :: Int -> Intfib n = fiben 0 1 n

    fiben :: Int -> Int -> Int -> Intfiben a b n = $ase n of

    0 -> an -> fiben b (a + b) (n - 1)

    This is a slight imrovement over the C code, but not much. ;ote that the tye of fib4en isGnt to nt to nt to ntG, meaning that it takes three nts and returns an nt. 9ore on that later.$lso note that this uses a recursive function. ecursion is every!here in Haskell. 9ost ofyour 1looing1 functions !ill involve recursion instead.

    The real imrovement over C comes in defining the seIuence#

    fibs :: &Int'fibs = 0 : 1 : & a + b (a, b) !- %ip fibs (tail fibs)'

    on1t be scared. 2nce you understand this function, you !ill understand at least half of the

    intracies of Haskell. /et1s take it from the to. n Haskell, lists are !ritten as follo!s#

    & 4, , , , '

    This is the list of , then %, then 8, etc. The 1#1 oerator is used to comose a list by sticking avalue on the front (left). 7or instance#tep = 1 : & 4, , 5 '

    is the list + ', , %, * .

    That means that in the above code, fibs is a list of nt, and its first t!o values are ?ero andone. That1s good so far. $t least the first t!o values of 1fibs1 !ill be right. The ne6t artdefinitely looks !eird. t1s a tool found in Haskell called a 1list comrehension1. n Part , said that instead of making sace and then filling it !ith the right values, you can define theright values. Here1s that sentence, restated for list comrehensions# G@ou can define the

  • 8/12/2019 Haskell Tutorial for C Programmers

    10/44

    values of the list rather than make sace and then fill them in.G /ist comrehensions !orklike so#

    & fun$ !- list, bool.un$ '

    This e6ression makes a ne! list. n the middle, there1s a 1list1, and it sits out values called 6.These are the values of the list in order. f 1bool7unc 61 is True, then 6 !ill get used in thisne! list. ;o bool7unc is in the 1fibs1 e6amle, but include it here because it can also bee6tremely handy. $ssuming 1bool7unc 61 !as true, 1func 61 alies some function to the valueof 6, and the result is then ut ne6t in line in the final result. Here1s an e6amle of a list andits use in some list comrehensions, coied from using 4HCi#

    /relue> let nus = & 4, , , , 5, 11 '/relue> & + 1 !- nus '&5,2,,3,,1'/relue> & * !- nus, ! '&1,4,2,5'

    /relue> & * !- 3 : 1 : nus '&1,,,4,1,1,10,'/relue> & trin6 !- nus, ! 5 '&trin6,trin6'/relue>

    ;ote that the order !as reserved in each case. This is very imortant for our e6amle. $lsonote that the tye of the list comrehension !as not necessarily the tye of nums, nor did 6actually have to be used in the function. /et1s return to 1fibs1.

    2.+ Part 0 -aking 'ense of "fibs" and !( La5( 67aluation is Im#ortant

    :e !ere !orking on a definition for the list of 7ibonacci numbers. Here is the e6amleagain#

    fibs :: &Int'fibs = 0 : 1 : & a + b (a, b) !- %ip fibs (tail fibs)'

    5o !hat the heck is 1(a, b)1 and 1?i fibs (tail fibs)1 and all that< :ell, Haskell has a moree6ressive tye system than most other languages. $s in Python, 1(a, b)1 is a tule, meaning

    t!o values stuck together. t1s a convienent !ay to store and ass multile values, much moreso than structs. ust add arentheses and enough commas, and you ass the grou of valuesaround as you lease. The only trick is that Haskell e6ects you to be consistent, and thatmeans having the right tye. The code adds 1a1 and 1b1 together to get a number in the7ibonacci seIuence, so !e kno! that1a1 and 1b1 are integers. Clearly, 1(a, b)1 is of tye 1(nt,nt)1, !hich is stated as follo!s#

    (a, b) :: (Int, Int)

    :e get these values labeled 1(a, b)1 from the list defined by 1?i fibs (tail fibs)1. Therefore 1?ifibs (tail fibs)1 is of tye 1+(nt, nt)1, a list of %-tules of an nt and an nt. 9ore clearly#

    %ip fibs (tail fibs) :: &(Int, Int)'

  • 8/12/2019 Haskell Tutorial for C Programmers

    11/44

    @ou can use 4HCi and Hugs to rint these tyes. The 1#t1 command, follo!ed by a variable orfunction, !ill rint its tye. The follo!ing is at the 4HCi romt !ith the e6amle file thatincludes the fibs function loaded#

    *7ain> :t %ip fibs (tail fibs)

    %ip fibs (tail fibs) :: &(Int, Int)'*7ain>

    5o !hat is 1?i1< ts tye and general meaning are given here#

    The Prelude, section# Riing and Kn?iing /ists

    1?i1, as its name some!hat imlies, takes t!o lists and 1?is1 them together, returning a list oftules, !ith the left member of each tule being an item from the first (left) list, and like!isefor the right.

    /relue> %ip & 1, 2, , ' & u$8, u$8, u$8, 6oose '&(1,u$8),(2,u$8),(,u$8),(,6oose)'/relue>

    $nd !hat about 1(tail fibs)1< 1tail1 is a retty straightfor!ard function# it chos off the firstitem of a list and returns the remainder. That statement can be slightly misleading. 1fibs1doesn1t get altered by using 1tail1 on it as said before, Haskell doesn1t have an udateoeration. nstead, 1tail1 "ust comutes the roer result and returns it, rather than altering1fibs1 itself.

    /relue> tail & 10, 0, 20, 40, 50 '&0,20,40,50'

    /relue>

    :ell, that makes it seem like 1?i fibs (tail fibs)1 robably has the right tye, but !hat is it Intfib n = fiben 0 1 n

    fiben :: Int -> Int -> Int -> Intfiben a b n = $ase n of

    0 -> a

    n -> fiben b (a + b) (n - 1)

  • 8/12/2019 Haskell Tutorial for C Programmers

    13/44

    :hen !as !riting this e6amle, !rote the tye of fib first, then the tye and definition offib4en, then finally the definition of fib.

    7or those of you !ho are not accustomed to !riting recursive functions, Haskellrogramming often reIuires them. 2ften these recursive functions need subsidiary functions,

    !hich either 1frame1 the main oeration of recursion, or erform a simle task that kees themain recursion function clean. n either case, the subsidiary functions can be !ritten later,after the ma"or recursive oeration is clearly defined including end conditions.

    n general, it is a good idea to concentrate on the most crucial asect of a iece of code !henrogramming, but Haskell1s design greatly reinforces this. The definition of subsidiaryfunctions, such as the 1setu1 !here fib calls fib4en !ith arameters 10 ' n1, can !ait until thefunction itself has been !ritten. This is true even though the tye of fib !as obvious from the

    beginning. /ike!ise, Haskell makes !riting trivial functions like that so Iuick that they cangenerally be ignored !hile thinking about the larger icture. These things are likely to changethe !ay that you code, and robably in a good !ay.

    3.2 Part II0 *unctions 4ut %eall( a 'idetrack to T(#es

    $s !e move on, the other half of Haskell1s general usage looms. This half is about functions.

    5o !hat is a function< $s this tutorial1s alignment indicates, !e1ll comare CFCDD to Haskell.n C, a function is a seIuence of commands that have their o!n namesace, are called duringe6ecution and assed arameters, inherit the namesace of the scoe in !hich they are

    !ritten, and return a value to their caller. n Haskell, most of that is true, e6cet of coursefunctions in Haskell are not seIuences of events, but e6ressions and definitions. There is ama"or difference bet!een C and Haskell, ho!ever, and it concerns the amount of fle6ibilitythat functions have.

    n C, functions take arameters and return a single value. :e1ve already seen that Haskell hasmany !ays to grou values, like several other languages. The t!o most common of these arelists and tules, and these can be the return tye from a function. To sum them u, in Haskelllists are variable length and hold values of the same tye, and tules are fi6ed length and canhold values of different tyes. Here is an e6amle of a function tye that returns a tule#

    split"t :: Int -> &a' -> (&a', &a')

    1slit$t1 takes an nt and a list and returns a tule. The left value in the tule is the first nvalues in the list, and the right value is the rest of the list, !here n is the first arameter. Thisfunction is in the Prelude, and its descrition can be found here#

    The Prelude, section# 5ublists

    :e1ve already seen lists in a tye#

    fibs :: &Int'

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:17http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:17
  • 8/12/2019 Haskell Tutorial for C Programmers

    14/44

    5ince the fibonacci numbers gro! raidly, but 1nt1 is 3%-bit, it !ould robably have beenbetter to use 1nteger1, Haskell1s built-in infinite-recision integer storage.

    fibs ## +nteger

    $nd this is a function tye. The function takes ?ero arameters and returns a list of ntegers.This isn1t a trick of Haskell1s synta6. 1fibs1 really is a function that, when evaluated!ill returnnumbers comrising the fibonacci seIuence. That kind of logic is !hat lets Haskell1scomilers roduce code !hich runs Iuickly and lets Haskell rogrammers !rite codeefficiently.

    3.3 Part III0 -ore T(#es 4ecause Haskell Is "Pol(mor#!ic"

    t1s time for a brief +not so brief digression about tyes. $s you1ve noticed, the trend seems tobe to call everything a 1function1. $nd that1s true. Take 11 for e6amle. :hen you use anumber 11 hardcoded into your code, it looks to you like the number . >ut !hat is it toHaskell< Tye 1#t 1 into Hugs or 4HCi. :hat do you get< @ou get some !eird "unk#

    /relue> :t 44 :: (u t) => t/relue>

    That looks like it1s a function that1s taking a arameter. t1s not, and the key is the 1OU1 arro!rather than the 1-U1 arro!. The tye given is read as follo!s# Gfour is of tye 1t1, !here 1t1 is inthe class 1;um1.G :hat1s the class 1;um1< :ell, it1s the class that all numbers belong to. The

    real ans!er is that Haskell has something C doesn1t# true #ol(mor#!ism.

    This is an imortant term and it needs some illustration. 9ost CDD rogrammers are familiar!ith the term 1overloading1, !hich means that a function is defined for more than one set of

    arameter tyes. 7or instance, addition and multilication in CFCDD are overloaded, allo!ingthe follo!ing combinations to occur#

    int a = 4, b = 5;float = 5, # = 0;

    $out !! a + b;

  • 8/12/2019 Haskell Tutorial for C Programmers

    15/44

    operator* (int, int);operator* (int, float);operator* (float, int);operator* (float, float);

    The C comiler icks the aroriate tye at comile time. The key distinction bet!een

    olymorhism and overloading is that in CFCDD, !hich uses overloading, each functionabove must be !ritten searately. n CFCDD, any function besides those above that uses eitheran int or a float must secify !hich one it e6ects, or must itselfbe overloaded. This bring usto the idea of classes.

    7or !hat tyes is 1D1 defined in CFCDD< t is ossible to overload the oerator for ne! tyesdefined by a user, but those ne! tyes !ill not be interchangeable !ith ints, floats, or othernumeric tyes. :hat this means is that e6isting sort functions such as merge5ort andIuick5ort !ould need to be re!ritten to sort values of the ne! tye. n constrast, here is thetye of merge5ort in Haskell#

    er6eort :: r a => &a' -> &a'

    :hat is going on< $gain, there are t!o arameters listed, not three. The first thing thataears to be a arameter is actually a class restriction. 1merge5ort1, as you !ould e6ect,takes a list of ob"ects of some tye (tye 1a1), and returns a list of ob"ects of the same tye. 5o!hy is the follo!ing tye not sufficientut!ithout that, is of tye 1a1, !here 1a1 is in class 1;um1, or more simly, is of tye 1a1 in class1;um1. $nd that is imortant, because 1D1 is defined for all member tyes of class ;um,meaning that 11 is definitely a legal arameter for this function#

    oubleIt :: u a => a -> aoubleIt n = n + n

    1-1 and 1Q1 are also defined for all member tyes of ;um, so is also allo!ed for this function#

    fib/ol# :: (u a, u b) => a -> b

  • 8/12/2019 Haskell Tutorial for C Programmers

    16/44

    fib/ol# n = fiben/ol# 0 1 n

    fiben/ol# :: (u a, u b) => b -> b -> a -> bfiben/ol# a b n = $ase n of

    0 -> an -> fiben/ol# b (a + b) (n - 1)

    That is our first Haskell fib function, but !ith the tyes changed. The names have an added1Poly1 so that an error doesn1t occur in the e6amle files because of a reused name. The tyeof 1fibPoly1 is read, GfibPoly is of tye 1a1 to 1b1, !here 1a1 is a member of class ;um and 1b1 is amember of class ;um.G There is only one 1OU1 arro! because there is only ever one section ofthe tye that describes class restrictions. The arentheses are reIuired.

    :hy !ould !e do this< 5houldn1t !e ick a single tye for b rather than use a class< Here1san e6amle. :hat if you !orked on a grou ro"ect, and t!o eole need to calculatefibonacci numbers< $nd for reasons of their o!n, one needed an nt returned and the otherneeded an nteger< 2r a ouble< :ould you !rite the code t!ice !ith different tyes< f you

    !ere using C you !ould. @ou1d have to. Ksing general tye classes allo!s code reuse in a!ay that is imossible in other languages.

    $lso notice that in the initial call to 1fib4enPoly1, the third arameter is 1n1, the first arameterof 1fibPoly1, and that the tyes of 1fibPoly1 and 1fib4enPoly1 seem to make note of this. Thereason !rote 1fibPoly1 !ith a different return tye from its arameter is that the follo!ing!ould be common#

    fib :: Int -> Inte6er

    :e only need nt-si?ed storage of our counter inut, but !e may need nteger-si?ed storage

    of the result. Ksing t!o searate tyes allo!s this. $lso, carefully check ho! tyes flo! in1fib4enPoly1. The math does not mi6 arameters of tye 1a1 and 1b1, and a arameter of tye 1b1is also used as the final return value. The tyes match not only e6ternally but internally.7ollo!ing tyes through code in this manner !ill be imortant for debugging.

    Continuing on!ard, in the fib e6amle !e used 1tail1. Here is its tye#

    tail :: &a' -> &a'

    n C, tail !ould have to be reimlemented for every tye of list you used. That sounds like aslightly contrived roblem, so !hat about 11, the inde6 oerator< n most other languages,inde6ing a list is a built-in oerator, because it has to !ork for every kind of array. 5o it1s notactually a function. $nd so on. Everything in C is either overloaded, built in, or !orks foronly one tye. There are a fe! e6cetions, generally involving casting to or from 1(void Q)1,

    but those are far outside the scoe of this tutorial.

    The oint is, you1re going to see 1;um a OU1 at the beginning of tye signatures, as !ell as 1a1and 1b1 inside tye signatures. Here, 1a1 and 1b1 are tye variables, used by the comiler solelyto determine roer tyes for comilation. 2ccasionally you !ill get messages such as 1can1tdetermine tye1, or 1tye mismatch1. The second means the you1ve done something !rong, butthe first usually means that a tye variable can1t be inned do!n to a single tye for a

    function that you1ve !ritten. This can haen for the simlest of reasons#

    ain = puttr@n (sAoB 4)

  • 8/12/2019 Haskell Tutorial for C Programmers

    17/44

    Previous versions of 4HC !ould not accet this. Here1s !hy# 1ut5tr/n1 takes a string anduts it on the screen. has a 1olymorhic1 tye, i.e. it is a member of a tye class, not definedas a secific tye. 1sho!1 takes anything that can be turned into a string (basically), and so itdoesn1t secify a tye for 11 either. This leaves the comiler in a Iuandry, because no secifictye is indicated any!here, and it !ill comlain. To resolve it, add the tye definition like so#

    ain = puttr@n (sAoB (4 :: Int))

    2r nteger, or ouble, or !hatever. This !ill be handy !hen you try to test generali?edfunctions, and you1ll need it in a fe! other !eird cases as !ell.

    2ne last note. @ou can define the tye of multile functions simultaneously#

    add2ne, subtract2ne ## nt -U nt

    This can be handy.

    3. Part I0 *unctions Alread(

    >ut !e !ere talking about functions. $s you may have noticed, it seems like anything can!ork as a arameter or return value for a function. This is absolutely true, as long as the tyesmatch. 7or instance, let1s take a look at the e6tremely useful 1ma1 function#

    ap :: (a -> b) -> &a' -> &b'

    >y no! you can robably read that, strange as it may be. Gma is of tye function a to bfollo!ed by a list of tye a and returns a list of tye bG. t1s taking a function as a arameter.

    ;ot only that, but a olymorhic function, !ith no tye restrictions. $nd look at the othert!o items. The function it takes is from a to b, and then it takes a list of tye a and returns alist of tye b. :ith a name like 1ma1, it1s retty clear !hat should haen !hen you use it#

    foo@ist :: &Int'foo@ist = &2, 1, 5, 4'

    bar :: Int -> Intbar n = n - *7ain> ap bar foo@ist&1,-1,2,'*7ain>

    ;othing to it. n the ast a tye for at least 1foo/ist1 or 1bar1 !ould have been reIuired or Hugsand 4HC !ould have comlained that the tyes could not be fully determined. 1ma1 is in thePrelude, and its descrition can be found here#

    The Prelude, section# /ist 2erations

    The e6amle using 1ma1 sho!s that you can !rite functions !hich take functions asarameters. This can be fun and very useful. ;o! let1s try something stranger#

    subCa$A.ro?en :: &Int' -> &Int'

    subCa$A.ro?en = ap (10 -)

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:11http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:11
  • 8/12/2019 Haskell Tutorial for C Programmers

    18/44

    :hat the heck< 7irst, for this to !ork there do need to be arentheses around the 1-1 and the1'01. 5econd, !hat does this do< :e1ll take this one ste at a time again. 1('0 -)1 is a function.t takes a number and returns ten minus that number. Kse 1#t1 in Hugs or 4HCi to find out itstye#

    *7ain> :t (10 -)(10 -) :: (u t) => t -> t*7ain>

    5econd, 1ma1 takes a function as its first arameter. There1s a reason that Haskell uses arro!sto define tyes, rather than a arenthesi?ed list. 1ma1, alied to 1('0 -)1 has the follo!ingtye (again, check in Hugs and 4HCi)#

    *7ain> :t ap (10 -)ap (10 -) :: (u t) => &t' -> &t'*7ain>

    t takes a list of ;um members (all the same tye of ;um members, mind you) and returns alist of the same tye (again, the same tye member of ;um). This is constrained to +nt -U+nt by subEach7romTen1s tye signature. $lying the 1ma1 function to less than its full listof arguments like this is called 1artial evaluation1. @ou take a function, give it some of its

    arameters, and you1ve got a function that takes the rest of the arameters. @ou can evenname this 1in-bet!een1 state, since it is "ust a function like anything else. Here is1subEach7romTen1 in action#

    *7ain> subCa$A.ro?en &4, , , 11'&,4,2,-1'*7ain>

    t does !hat you think it should, given ho! named it. emember that alyingsubEach7romTen to a list, even a named list, does not change that list, but merely returns theresult.

    Take some time no! to lay around !ith artial evaluation, in addition to the list functionsmentioned before and list comrehensions. emember that functions grab their arameters1eagerly1, so you have to ut arentheses around any arameters that are comosed of afunction !ith its o!n arameters.

    'ection III0 /ow Let"s %eall( rite *unctions

    .1 Part I0 Did 9ou Take T!at 4reak Here Are Patterns

    Hoefully you are no! comfortable defining and using functions in Haskell using yourchoice of Hugs, 4HC, or 4HCi. ;o! it1s time to talk about all the !ays in !hich functionscan be defined. f you are not ready, re-read some of the earlier material and set u one of the

    rograms for using Haskell. The rest of this !ill only hel you if you1re trying it for yourself.

    Each function has a tye. Even functions !ith no arameters each have a tye, i.e. global andlocal variables. t is not al!ays necessary to !rite this tye, as Haskell comilers can

  • 8/12/2019 Haskell Tutorial for C Programmers

    19/44

    determine it. Ho!ever, !riting it is a good ractice and sometimes a necessity. :e are aboutto cover a lot of synta6, so after reading this section, it !ould be a good idea to read the Tourof the Haskell 5ynta6 listed in the introduction.

    There are a fe! e6amles !e can go through to make that age clearer. 7irst, a simle

    function that !alks do!n a list and sums its members#

    su"ll :: u a => &a' -> asu"ll (:s) = + su"ll ssu"ll &' = 0

    This is a recursive function. t takes a list of 1a1 in ;um and returns an 1a1. Ho!ever, thereseem to be t!o definitions for sum$ll. $nd there are. This is ho! attern matching !orks.The t!o definitions have different secifications for their arameters, and each time sum$llis called, !hichever attern matches the arameters !ill be evaluated. /et1s look at eachdefinition. The second definition is the clearest. 1+1 is the emty list, and sum$ll of an emty

    list is defined here as ?ero. The middle line has something odd about it, though. 1(6#6s)1 islisted as a arameter, as if !e !ere trying to stick something on the front of a list. n essence!e are, because this attern takes aart its inut. There are a fe! atterns !hich do this, andthis feature of Haskell makes lists very easy to use. To restate, !hen 1(6#6s)1 is !ritten as a

    arameter in a function definition, it !ill only match lists !hich have an item stuck on thefront. n other !ords, it !ill match lists !ith at least one member. The choice of variablenames 161 and 16s1 is comletely arbitrary, but since 161 !ill be 1bound1 to the first member ofthe list and 16s1 !ill be 1bound1 to the remainder of the list, it is some!hat natural to !rite one161, and then the remaining 16s1 !hen describing the list.

    :hen the attern 1sum$ll (6#6s)1 matches the inut, that is, !hen 1sum$ll1 is called !ith a list

    that has at least one value, the first definition !ill be evaluated. This !ill return the result ofadding said first value to the result of calling sum$ll on the rest of the list. Patterns arechecked to-to-bottom, so !hen 1sum$ll (6#6s)1 fails to match, 1sum$ll +1 is checked. 5incethe only attern that could fail to match 1sum$ll (6#6s)1 is an emty list, 1sum$ll +1 !illdefinitely match, and it returns ?ero. This is the end condition for the recursion.

    This sort of function is very common in Haskell. Pattern matching lets us avoid comlicated1s!itch1 statements or 1if1 blocks in favor of simly !riting searate definitions for distinctinuts. This allo!s code to be clear and concise. Patterns can also be more secific. The fibe6amle can be re!ritten as follo!s#

    fib/at :: (u a, u b) => a -> bfib/at n = fiben/at 0 1 n

    fiben/at :: (u a, u b) => b -> b -> a -> bfiben/at a D 0 = afiben/at a b n = fiben/at b (a + b) (n - 1)

    $gain, the names are changed to avoid conflicts in the e6amles, adding 1Pat1. Here a literal(101) is used to match a attern, and that is fine, too. $lso note the underscore (1N1) in the firstdefinition. The underscore matches anything, "ust like a variable name, but does not get1bound1 to its arameter. This can make code clearer !hen a arameter is not used. n thiscase, !e do not care about the second arameter, since !e are only matching against the thirdand returning the first.

  • 8/12/2019 Haskell Tutorial for C Programmers

    20/44

    .2 Part II0 After Patterns &uards

    5ometimes functions need more comlicated !ork to choose bet!een definitions. This can be

    done !ith guards, sho!n here#

    sAoB?ie :: Int -> Int -> trin6sAoB?ie Aours inutes

    Aours == 0 = 1 ++ : ++ sAoB7in ++ a Aours != 11 = (sAoB Aours) ++ : ++ sAoB7in ++ a Aours == 1 = (sAoB Aours) ++ : ++ sAoB7in ++ p otAerBise = (sAoB (Aours - 1)) ++ : ++ sAoB7in ++ pBAeresAoB7in

    inutes ! 10 = 0 ++ sAoB inutes otAerBise = sAoB inutes

    gnore the lines after the 1!here1 for the moment. 1sho!Time1 has only one definition clause,but it is broken u into three guards. Each guard has a boolean e6ression, and they arechecked in order. The first !hich is found to evaluate to True !ill have its corresondinge6ression evaluated and returned. The function !ill be eIual to that e6ression for the casethat that guard is true. 1other!ise1 is eIual to True, and !ill therefore al!ays be acceted if itis reached. 1other!ise1 is a convenience, not a necessity. 1DD1 is the list concatenation oerator.t is used here for the follo!ing reason#

    trin6 :: &EAar'

    5o all of that makes sense e6cet for the 1!here1 stuff. Here thre! in something e6tra, andused a 1!here1 clause to define a local function, in this case a variable called 1sho!9in1.1sho!9in1 is a variable in the traditional sense, but it is also a function here in Haskell, soinstead of an 1if1 statement or 1case1 statement, used guards again to describe its t!odefinitions.

    n all, this function takes an hour (hoefully from 0 to %3) and minutes (hoefully from 0 to*B) and rints the time from them. 1sho!9in1 is a local variableFfunction, defined in the!here clause. 4uards are used both to define 1sho!Time1 and 1sho!9in1.

    t is imortant to note that the variables defined in 1!here1 clauses and their cousins, 1let1

    clauses, are only in scoe for the attern in !hich they e6ist. 5o a function defined !ithmultile atterns can1t use a 1!here1 clause to define a local variable across all of them.

    .3 Part III0 "If"

    mentioned 1if1 statements "ust above, and Haskell has them, but they are al!ays if-then-else.Haskell doesn1t have much use for a function that doesn1t return some kind of value, so 1if-then1 doesn1t !ork. That said, here1s a simle e6amle#

    sAoB7s6 :: Int -> trin6sAoB7s6 n = if n ! 0 tAen failin6 else passin6

  • 8/12/2019 Haskell Tutorial for C Programmers

    21/44

    ;ot much to it. 5ince 1sho!9sg1 has a return tye of 5tring, the values in both the 1then1clause and the 1else1 clause have to also be of that tye. 1if1 does not need to be the entiredefinition of a function. 7or instance#

    sAoB@en :: &a' -> trin6

    sAoB@en lst = (sAoB (tAe@en)) ++ (if tAe@en == 1 tAen ite else ites)BAeretAe@en = len6tA lst

    . Part I0 Indention '(nta)

    @ou may have noticed that use indention to indicate lines that are art of a block of sourcecode. This is not simly good style, but it is also art of Haskell1s synta6. ndentation denotesstructure. 5ecifically, changing the indentation from one line to the ne6t indicates that a

    block of code has begun or ended. $lso, Haskell !ill not let you lace the definitions for t!ofunctions one line after another. nstead it demands a blank line to indicate that the definitionof a function has truly finished. This all enforces good style, and it greatly reduces theamount of "unk synta6 in the language, such as 1W1, 1X1, and 11.

    .+ Part 0 And Lambda *unctions

    4iven a rogrammer1s ability to define functions locally in Haskell, you might ask, Gs there

    an even more brief !ay of defining functions * 4 + #) :: u a => a -> a -> a

    :hat is this you ask< t all starts !ith the 1(Y1 right at the beginning. 1Y1, you see, looks a littlelike the greek letter lambda, !hich haens to be the symbol used for Haskell itself#

    htt#FF!!!.haskell.orgF

    1/ambda calculus1 is a branch of mathematics that deals !ith functions created on the fly.

    There1s a lot more to it, such as its lace in comutation theory, etc. @ou can find out moreabout it other laces. The oint is that !hen you !rite 1(Y1, you have started a 1lambdae6ression1, !hich generally look a lot like the one above. t has 1(Y1, then some variablenames (usually short ones), a 1-U1 arro!, and an e6ression !hich uses those variables. $nd ofcourse a 1)1. 1m sure you can figure out !hat this does. t defines a function and uses it right!here it is defined. 7or e6amle#

    /relue> ap (F -> tAe ++ sAoB ) &1, , 2, 4, 5'&tAe 1,tAe ,tAe 2,tAe 4,tAe 5'/relue>

    mention lambda functions because they come in handy, but also because they are used oftenin the more comlicated e6amles. 2f course, lambda functions cannot be recursive, since

    http://www.haskell.org/http://www.haskell.org/
  • 8/12/2019 Haskell Tutorial for C Programmers

    22/44

    they !ould need a name in order to refer to themselves. 5o they are good for those cases!here a function is needed only once, usually to define another function.

    ., Part I0 Pol(mor#!ic T(#es and T(#e Constructors

    The simlest Haskell rogram is the follo!ing#

    ain = return ()

    The variable 1main1 is a reserved !ord, and !hatever its value is, the rogram e6ecutes. Hereis the obligatory GHello :orldG rogram#

    ain = puttr@n Gello Horl

    $nd the tye of 1main1#

    ain :: I ()

    This is another !ay of saying Gmain is of tye something or otherG. :ell, that1s ho! it looksany!ay. :hat !e have here are e6amles of t!o strange things at once. That haens a lot!hen you1re learning Haskell, and that1s !hy 1m !riting such a long tutorial in the first lace.1()1 is a tye. The only value of tye 1()1 is !ritten 1()1. $nother !ord for this tye and itssingular value is 1null1. 5o this tye can be read Gmain is of tye 2 nullG. >ut !hy is it readthat !ay< :hat does it mean to ut one tye after another< 2 is not a tye. The !ord 121 isonly art of a tye. 12 a1 is a tye. 121 is a tye constructor !hich takes a tye as a

    arameter. ee breath.

    This is not the same thing as a class. :hen !e !ere talking about classes, said thatfunctions !ere olymorhic, meaning that they could oerate on values of any tye rovidedthat the roer functions !ere defined for it. @ou can create a tye and make it a member of

    ;um, as long as it has 1D1, 1-1, and 1Q1 defined for it, as !ell as having eIuality defined. f youdo that correctly, any function !hich has 1;um a OU1 at the beginning of its tye !ill accetyour ne! tye and everything !ill !ork fine. >ut 121 isn1t a class, or a olymorhic function.This is something stranger. t is a olymorhic tye.

    id that make sense< $ tye that takes another tye as a arameter< /et1s look at an e6amlefrom the standard libraries#

    ata 7a#be a = otAin6 ust a

    This tye can be found here#

    htt#FF!!!.haskell.orgFghcFdocsFlatestFhtmlFlibrariesFbaseFata-9aybe.html

    This is a 1data1 tye definition. The values on the right are searated by 11, the ie symbol,!hich can be read here as GorG. This tye says, Ga value of tye 19aybe a1 can be 1;othing1, or

    can be 1ust a1G, that is 1ust1 follo!ed by a value of tye 1a1. Here1s an e6amle using 9aybe inattern matching#

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Maybe.htmlhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Maybe.htmlhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Maybe.html
  • 8/12/2019 Haskell Tutorial for C Programmers

    23/44

    sAoB/et :: 7a#be (trin6, Int, trin6) -> trin6sAoB/et otAin6 = nonesAoB/et (ust (nae, a6e, spe$ies)) = a ++ spe$ies ++ nae ++nae ++ , a6e ++ (sAoB a6e)

    1sho!Pet1 has t!o atterns. The first matches a value of 1;othing1, the first 1data constructor1

    for 9aybe. There are no variables after 1;othing1, "ust as there are no tyes listed after1;othing1 and before the 11 in the tye definition for 19aybe a1. The second matches a value of1ust1, the second 1data constructor1 for 9aybe. 1ust1 does have a tule after it, "ust like in thetye definition, and arentheses are used to grou these t!o things in the attern. The !ords1ust1 and 1;othing1 are arbitrarily chosen, although good choices. t is imortant that the firstletter is caitali?ed. $s you may have noticed, throughout Haskell, variables have lo!ercasefirst letters and tyes have uercase first letters. This is a art of Haskell1s synta6. ataconstructors are not variables, and so the convention is e6tended to reIuire their first letters toalso be caitali?ed.

    .: Part II0 T!e I$ -onad

    5o let1s get back to 1main1 and its tye, 12 ()1. 2 is a olymorhic tye. >ut !hat is it Int -> &Int'soe.un$

    ain = oputtr propt 1a !- 6et@ineputtr propt b !- 6et@ineputtr@n (sAoB (soe.un$ (rea a) (rea b)))

    Here1s !hat1s going on# The 2 9onad binds blah blah blah that1s all in the other tutorials andyet you1re reading this. /et1s try again.

    Here1s !hat1s going on# $ll of that 1variable eIual at all times1 stuff mentioned in revious

    sections doesn1t !ork !ith F2. $fter all, you have to call 1get/ine1 several times, and itdoesn1t al!ays return the same value. @ou can1t say that the function 1get/ine1 is GeIualG to

  • 8/12/2019 Haskell Tutorial for C Programmers

    24/44

    anything, since its value may be different every time it is referenced. This is in contrast to avalue, like 11, !hich !ill al!ays be the number . 5o 2 is hard to do if you !ant a languagethat has true GeIualityG !hen you !rite an assignment. T!is !as actuall( been t!e biggeststumbling block for functional language design since t!e idea of functional languages

    arose. Haskell !as a solution.

    9ost functional languages break their 1functional model1 to handle 2, but of course Haskelldoes something !eirder. There1s an obscure branch of mathematics, namely monads, thatconcerns state transformation functions. The authors of Haskell used it to let you !ritemathematical functions that denote changes in the !orld1s state !ithout breaking that niceeIuality stuff. +Ho!1s that for simle< 5ee ho! made it all make sense by aealing to ahigher authority< Haskell !orks by magic -Eric

    >riefly, the 2 monad takes the state of the !orld, alters it !ith some function, and asses itfor!ard to be the inut for another 2 function. n the e6amle, the functions 1ut5tr1,1get/ine1, and 1ut5tr/n1 are members of 2. 1>inding1 them to 1main1 by using the 1do1 notation

    means that !hen 1main1 is evaluated, they !ill be evaluated in order, "ust like you1d e6ect.Thus the main function of the rogram above !ill ut a romt on a screen and read in astring, and then do it again, then rint something. The 1(read 6)1 function takes a string andreturns a number of !hatever tye is needed, assuming the string arses. The 1sho!1 function!ill take the result from 1some7unc1 and turn it into a string so that ut5tr/n can dislay it. !ill return to this code and make it useful later.

    The descrition of 2 may sound like 1imerative1 behavior, and it is, !ith a t!ist. nut andoutut need to haen in a certain seIuence in a rogram, but a mathematical function1s artscan be determined in any order as long as it eventually finishes. 5eIuence doesn1t matter forthe evaluation of a mathematical definition, and most Haskell code is !ritten in that manner.5o !hat about inut and outut< Can they be mathematically described< $s it turns out, theycan. 9onad theory means that a function can be GeIualG to the act of transforming a state.The mathematical frame!ork for monads catures the idea of seIuenced actions, and that letHaskell1s creators give 12 a1 a tye that could be used "ust like any other tye. :hen aseIuence of monad functions are evaluated, for instance !hen 1main1 is evaluated, the monadfunctions are alied in seIuence to the initial state. >efore that evaluation, Haskell gets totreat functions of tye 12 a1 "ust like anything else, i.e. as e6ressions !aiting to beevaluated. That means that the 12 a1 tye doesn1t have to be a secial, builtin art of Haskell,even though inut and outut have to be art of the standard libraries and imlemented !ithsystem calls. t does mean that doing 2 in Haskell means using a olymorhic tye as !ell

    as a mathematical theory that is rather obtuse. That1s !hy 2 is so far do!n in this tutorial.

    $ll Haskell functions carry around this mathematical frame!ork (GeIualityG) and unlessother!ise noted, they are la?y. This means that the only thing that forces evaluation is

    binding an 12 monad1 function to 1main1. /ot!ing is e7er e7aluated unless it is going to bet!e return 7alue of an e7aluated "monad" function or unless it is needed to com#ute

    suc! a return 7alue.That the 12 monad1 forces evaluation isn1t really imortant, but it !ille6lain some odd behavior if you start doing Gout thereG coding in Haskell. There are eager,or 1strict1 functions in Haskell !hich, !hen evaluated, !ill first fully evaluate their

    arameters. These are usually marked in the documentation.

    t is ossible to use the 2 monad, illustrated above, to !rite imerative-style rograms inHaskell. That is a direct result of the behavior of the 2 monad. oing so !ould be

  • 8/12/2019 Haskell Tutorial for C Programmers

    25/44

    inaroriate, because Haskell has much more o!er than that. say that because have notseen any other tutorial do so, and think it is imortant.

    f you !rite rograms that call outside libraries, you1ll deal !ith the 2 monad a lot.Everything that deals !ith the rest of the comuter is art of the 2 monad, such as driver

    calls, net!ork libraries, file access, threading, and system calls. There are other monads inHaskell1s libraries, and you can also !rite your o!n. :riting your o!n monad for a ma"or

    ro"ect !ill robably be the other hard thing you need to do to fully understand Haskell, afterunderstanding 1foldr1 and variants. t1s retty hard, but not because it1s comlicated. :ritingyour o!n monad is hard because there1s so little to do that you1ll have to !ork to understand!hy that little bit of code is all you need. This tutorial ends !ith an e6tended e6amle thatdemonstrates ho! to !rite a monad from scratch, but it may not be necessary for a generalHaskell rogrammer to learn that.

    .; Part III0 Dissecting t!e I$ 6)am#le

    /et1s return to basic 2 monad usage. Here1s the e6amle main rogram again#

    soe.un$ :: Int -> Int -> &Int'soe.un$

    ain = oputtr propt 1a !- 6et@ineputtr propt b !- 6et@ine

    puttr@n (sAoB (soe.un$ (rea a) (rea b)))

    T!is is a general framework for learning Haskell.$side from altering the number ofarameters to 1some7unc1 (erhas ?ero), this is all you !ill really need for a main functionuntil you feel comfortable !ith Haskell. t is good enough for most simle tasks, and you canuse it to test out ideas in 4HC by relacing the definition of 1some7unc1 !ith !hateverfunction you1re trying to !rite. @ou !on1t need it for !orking in Hugs or 4HCi, but you !illif you comile !ith 4HC. n Hugs and 4HCi, you only need to make a source code file thatincludes some7unc1s definition.

    :hat said earlier about the indentation techniIue removing e6traneous synta6 isn1t Iuite

    true. 1W1, 1X1, and 11 do e6ist in Haskell. They are an alternative to the the !hitesace-definingnotation used here, and are sometimes but rarely referable. The !hitesace method is verysimle, and the e6amle sho!s most of its synta6. >locks begin on tabbed or saced lines andfurther indention is used for searate blocks. Ksing 1do1 signals to the comiler to e6ectindentation based on !hitesace unless you then use 1W1, 1X1, and 11.

    The 1(read 6)1 items use the 1read1 function found here#

    The Prelude# the 1read1 function

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Areadhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Areadhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Aread
  • 8/12/2019 Haskell Tutorial for C Programmers

    26/44

    1some7unc1 is !hatever you !ant to test. 5ince its return value is a arameter to 1sho!1,1some7unc1 can be defined !ith a variety of return tyes, such as 1nt1, 1+nt1, 15tring1, or even1(5tring, +nt)1. The tye of 1sho!1 is given here#

    The Prelude# the 1sho!1 function

    1sho!1 is a class method defined for members of the class 15ho!1. This is "ust like ho! 1D1 and1Q1 are class methods defined for members of 1;um1. @ou can see those here#

    The Prelude, section# the ;um class

    The tyes of the 2 functions, secifically 1ut5tr1, 1get/ine1, and 1ut5tr/n1, are given here#

    5ystem.2, section# 5ecial cases for standard inut and outut

    and also here, in the Prelude, !hich is !hy they are in scoe normally#

    The Prelude, section# 5imle F2 oerations

    $s you can see from the documentation, !hen ut5tr/n is alied to a 5tring, you get a valueof tye 12 ()1. The 1null1 means that no useful information is returned by the function. taltered the state of the 2 monad by utting something on the screen, and no value comes

    back from it.

    The 1V-1 arro! is used to bind the result of an 2 oeration to a variable. 1get/ine1 has a tyeof 12 5tring1. The 1do1 notation says that a monad function like 1get/ine1 can be refaced by a

    variable name and the left arro!. That variable name comes into scoe at that oint in thefunction and !hen the monad function is evaluated, and its return value !ill be assigned tothe variable. f a function is not refaced by a left arro! and a variable, then its return valueis ignored, although !hatever that function did to the state carried by the monad still haens.7or instance, if you do not bind the return value of 1get/ine1 to a variable, you don1t store theline the user tyed in, but it is still read in and buffers are messed !ith, etc., meaning thatanother get/ine !on1t return it.

    There is one e6cetion to this 1ignoring1 of return values not bound to variables. t is noaccident that the last line in the seIuence has the same return tye as main. :hen usingmonads to comose seIuences of oerations, the last line in a function must have the same 2

    tye as the function itself. :hen this is not natural, use 1return1 !ith an aroriate value#

    6etae1 :: I trin66etae1 = o

    puttr /lease enter #our nae: nae !- 6et@ineputtr@n ?Aan8 #ou /lease Baitreturn nae

    1ut5tr/n1 has a tye 5tring -U 2 (), but 2 () doesn1t match the tye of 1get;ame1, !hich is2 5tring. 1return name1 is used to end the function !ith a function of the roer tye, and toreturn the data !e !anted to return. :ithout the rely message, this function can be !ritten

    much more succintly#

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AShowhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3ANumhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/System-IO.html#g:20http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-IO.html#g:20http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:25http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AShowhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3ANumhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/System-IO.html#g:20http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:25
  • 8/12/2019 Haskell Tutorial for C Programmers

    27/44

    6etae :: I trin66etae = o

    puttr /lease enter #our nae: 6et@ine

    $s you can see, calling an 2 function !hich returns a value is the same as binding that value

    to a variable and then returning that value.

    This !hole monad issue looks imerative, and in some !ays, it is. 2nce you call 1some7unc1,you get a!ay from all that, and Haskell1s la?iness and eIuality become the norm. s all of thisnecessary< s it a good idea to have imerative-looking code calling la?y, functional code< nmy oinion, it can be. @ou get to secify the order of e6ecution for those oerations thatreIuire it (such as 2), and you get o!erful functional tools the rest of the time. @ou also geta hurt head. 5o take a break. need one from !riting all of this. The ne6t section !ill be onadvanced tye declarations.

    + 'ection I0 Haskell and 9ou

    +.1 Part I0 !ere Are t!e "*or" Loo#s

    $s you may have noticed, the aren1t any 1for1 loos in Haskell. @ou could !rite them using 2monad functions, but said that !asn1t the right thing to do. 5o !here are they< f you1vealready figured Haskell out, you can ski this section, but for those you like me that needed alot of assistance, read on.

    1for1 loos are unnecessary. ;ot "ust in Haskell, but in general. The only reason that you haveever used 1for1 loos is that you had to 1do1 something to a chunk of memory to store the rightvalue in the right sot. Haskell frees you from this, and !hen you got lost and !onder !hereyour 1for1 loos are, check here#

    bar :: Int -> Intbar =

    foo :: &Int' -> &Int'foo (:s) = bar : foo sfoo &' = &'

    That looks a little too easy, and is actually eIuivalent to 1foo O ma bar1. Here1s a lesscontrived e6amle. :hat if you !ere imlementing a hysics simulation, gravity fore6amle, and you needed to calculate a ne! osition of each ob"ect based on the otherob"ects1 ositions< The follo!ing function calculates art of the rocess, !hich is finding, foreach ob"ect, the sum of its mass times another ob"ect1s mass divided by distance, over allother ob"ects. n C, this !ould be accomlished by a air of nested for loos, the outer onereading the mass and osition from an array of ob"ects, and the inner one comuting mass'times mass% over the distance and summing it. Here are the tyes for that oeration inHaskell#

    --t#pes for Jariablest#pe 7ass = Kouble --onl# a t#pe renae, but useful for$larif#in6 paraeters

  • 8/12/2019 Haskell Tutorial for C Programmers

    28/44

    t#pe /os = (Kouble, Kouble, Kouble) --, #, %t#pe bL = (7ass, /os) --inter$Aan6eable BitA (Kouble,(Kouble, Kouble, Kouble))

    --list of fun$tions neee{-

    ?a8es a list of obLe$tsMeturns a list of (su of ass ties otAer obLe$t ass oJer istan$e forall obLe$ts)rer is preserJe-}

    --oJerall fun$tion t#pe$al$7assesJerKists :: &bL' -> &Kouble'

    That1s definitely the setu. defined some tyes for keeing track of the variables, listed themathematical oerations needed, and defined a tye for the overall function. n the above

    code, 1--1 indicated that the rest of the line is a comment. 1W-1 and 1-X1 oen and close blockcomments.

    The reason that searate this from the code is that it is unlikely to change, !hile code islikely to be altered, otimi?ed, debugged, etc. :ith some useful comments, here1s one !ay to!rite the code#

    --Gere Be pass tAe obLe$ts in as tBo paraeters to tAe Aelper fun$tion soBe $an iterate tBi$e--?Ais oes not $op# tAe list of obLe$ts$al$7assesJerKists :: &bL' -> &Kouble'$al$7assesJerKists obLs = $al$Gelper obLs obLs

    --?Ais is a fun$tion tAat $oputes a istan$e betBeen tBo /os Jalues, usein $al$77oKistNOP :: /os -> /os -> KoubleistNOP (1, #1, %1) (, #, %) = sQrt ( * + # * # + % * %)

    BAere(, #, %) = (1 - , #1 - #, %1 - %) --tAree assi6nents

    at on$e usin6 a tuple

    --?Ais iterates oJer tAe list of obLe$ts an $al$ulates tAe su for ea$A--It uses pattern at$Ain6 to re$urse an terinate$al$Gelper :: &bL' -> &bL' -> &Kouble'$al$Gelper (obL:obLs) obL@ist = (su ($al$77oK obL obL@ist)) : $al$Gelper

    obLs obL@ist$al$Gelper &' D= &'

    --?Ais $al$ulates tAe list of ass ties ass oJer istan$e for a sin6leobLe$t--It uses pattern at$Ain6 to re$urse an terinate an a BAere $lause to8eep tAe $oe $lear$al$77oK :: bL -> &bL' -> &Kouble'$al$77oK obLR(1, pos1) ((, pos):rest) = safeSalue : $al$77oK obLrest

    BAereist = istNOP pos1 possafeSalue = if pos1 == pos tAen 0 else 1 * < ist

    $al$77oK D &' = &'

  • 8/12/2019 Haskell Tutorial for C Programmers

    29/44

    thre! something e6tra in there, secifically 1ob"Z1 in front of 1(m', os')1. The 1Z1 is read1as1, and it means that 1ob"1 !ill refer to the !hole value of tye 12b"1, !hile 1(m', os')1 !ill

    attern match against the values in 1ob"1. t1s handy, because other!ise !ould have to !rite1(m', os')1 again !hen called 1calc99o1 recursively, and might make a tyo !hen did. $lso, it1s clearer. ;ote also that did not have to comletely 1take aart1 ob". left the

    value of tye 1Pos1 bound to 1os'1. $nd note that ut all the sub-comutations for 1dist@R1into one line to save sace. defined the tule 1(6' - 6%, y' - y%, ?' - ?%)1, and then bound it tothe attern of 1(6d, yd, ?d)1, thus defining 16d1, 1yd1, and 1?d1 ho! needed to. 7inally note thatdist is not evaluated in a call to calc99o if os' OO os%, and neither is m' Q m% F dist,!hich avoids the division by ?ero.

    can comare eIuality bet!een os' and os% because a tule of tyes !hich are all in theclass 1EI1 is also in the class 1EI1. The definitions allo!ing that are here, although you have toscroll do!n several ages#

    The Prelude, section# the EI class

    :hat you1re looking for is a line like this#

    (CQ a, CQ b) => CQ (a, b)

    :hen listed in the 1nstances1 section of the EI class, that means that some!here in the sourcecode for the Prelude, there is an instance of EI defined for 1(a, b)1 !ith the condition that botha and b are also members of EI. The definition of that instance is fairly straightfor!ard the

    oint is that it is there. >ecause it is resent, any tules of si?e % (and also those of manylarger si?es) !hose items are all members of the EI class, and those tules can be comaredusing 1OO1 and 1FO1 !ithout any further !ork on your art.

    1sIrt1 is a class function, and is defined (searately) for all tyes in the class 17loating1, !hichof course includes 1ouble1. The tye of 1sIrt1 can be found here#

    The Prelude, section# the 7loating class

    1sum1 is a olymorhic function, and is defined (one time) for all tyes in the class 1;um1,!hich also of course includes 1ouble1. The tye of 1sum1 can be found here#

    The Prelude, section# 5ecial 7olds

    could have had calc99o return the sum, but code !ill comile to a more efficient resultif the tasks are broken u, since 1sum1 in the Prelude is based on a tail-recursive and (

    believe) highly otimi?ed function. The definition of 1sum1 is in the Prelude, and more about1tail recursion1 can hoefully be found here#

    htt#FFen.!ikiedia.orgF!ikiFTailNrecursion

    5o !here are the 1for1 loos< Each recursive function iterates over a list, and the t!o togetheract as a nested air of 1for1 loos. This code is good, but there is a Iuicker !ay to !rite1calc9asses2verists1 and 1calc99o1, !ith the same tyes, and using a much simler

    heler function for 1calc99od1. Here is a cleaner imlementation#

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AEqhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AFloatinghttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:13http://en.wikipedia.org/wiki/Tail_recursionhttp://en.wikipedia.org/wiki/Tail_recursionhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AEqhttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AFloatinghttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#g:13http://en.wikipedia.org/wiki/Tail_recursion
  • 8/12/2019 Haskell Tutorial for C Programmers

    30/44

    --Gere Be use TapT instea of Britin6 tAe re$ursion out$al$7assesJerKists :: &bL' -> &Kouble'$al$7assesJerKists obL@ist = ap (FobL -> su ($al$77oK obL obL@ist))obL@ist

    --"6ain, Be use TapT instea of Britin6 tAe re$ursion out

    $al$77oK :: bL -> &bL' -> &Kouble'$al$77oK obL obL@ist = ap (7oKGelper obL) obL@ist

    --Gere Be onTt botAer spa$in6 out tAe $oe sin$e BeTre not forin6 a listan# ore--ote tAat tAis fun$tion no lon6er operates or returns a list7oKGelper :: bL -> bL -> Kouble7oKGelper (1, pos1) (, pos) = if pos1 == pos tAen 0 else 1 * /os -> KoubleistNOP (1, #1, %1) (, #, %) = sQrt ( * + # * # + % * %)

    BAere(, #, %) = (1 - , #1 - #, %1 - %)

    could have also avoided !riting 1m9oHeler1 by using a lambda function#

    --ae as aboJe$al$7assesJerKists :: &bL' -> &Kouble'$al$7assesJerKists obL@ist = ap (FobL -> su ($al$77oK obL obL@ist))obL@ist

    --?Ae $oe BAi$A aJois iJision b# %ero is noB in$lue Aere$al$77oK :: bL -> &bL' -> &Kouble'$al$77oK (1, pos1) obL@ist = ap (F(, pos) ->

    if pos1 == pos tAen 0 else 1 * < istNOP pos1 pos) obL@ist

    --?Ais is un$Aan6eistNOP :: /os -> /os -> KoubleistNOP (1, #1, %1) (, #, %) = sQrt ( * + # * # + % * %)

    BAere(, #, %) = (1 - , #1 - #, %1 - %)

    2r could have avoided !riting calc99o, but at that oint it gets ridiculous#

    --oB Be AaJe neste laba fun$tions BAi$A aJoi a fun$tion $all--ot reall# ne$essar#, sin$e no $larit# is 6aine

    $al$7assesJerKists :: &bL' -> &Kouble'$al$7assesJerKists obL@ist = ap

    (FobL1R(1, pos1) -> su (ap (F(, pos) ->if pos1 == pos tAen 0 else 1 * < istNOP pos1 pos)

    obL@ist) )obL@ist

    --?Ais is un$Aan6eistNOP :: /os -> /os -> KoubleistNOP (1, #1, %1) (, #, %) = sQrt ( * + # * # + % * %)

    BAere(, #, %) = (1 - , #1 - #, %1 - %)

    n any case, the division by ?ero !ill not be evaluated if os' OO os%. n the first e6amle,note that m9oHeler starts !ith a lo!ercase letter as all functions and variables do. $lso

  • 8/12/2019 Haskell Tutorial for C Programmers

    31/44

    note that none of these take much code to !rite. Haskell is like that. m9oHeler is artiallyalied in this e6amle. t is given only one of its t!o arameters !here it is !ritten incalc99o. The tye of 1m9oHeler ob"1 in that e6ression is#

    7oKGelper obL :: bL -> Kouble

    This in turn is suitable as a arameter to 1ma1, as it only takes one arameter, rather than t!o.

    ;ot every instance of a for loo should be turned into a 1ma1. n this case, there is thePrelude function 1sum1, !hich !ill take the list generated by the 1ma1 in calc99o andreturn the sum of its values. There is not al!ays a re-built function for your uroses. /istfunctions are art of Haskell1s core tools, and there are more advanced functions to use !henyou need them, such as 1foldr1 and its variants.

    /earning ho! to use 1foldr1 and 1foldl1 is a rite of assage for Haskell rogrammers. @ou !illlearn in time, by studying their definitions (in the Prelude) and definitions of other functions

    defined in terms of 1foldr1 and 1foldl1, such as 1concat1, 1or1, and 1sum1. 7or loos !ere "ust thebeginning. :hen you get a!ay from seIuential behavior, real o!er comes out. $lso, kee inmind that since foldr and ma are used every!here, 4HC has heavily otimi?ed them, andfunctions like them, so it1s a good idea to use them.

    +.2 Part II0 %emember La5( 67aluation It"s 'till T!ere

    This section fleshes out the fle6ibility of the Haskell tye system in a !ay that haven1t seendescribed for ne!comers before. Hoefully, your are at least familiar !ith the concet of a1Tree1, that is, a data structure !hich has nodes that contain values and may also oint tofurther nodes in the structure. 1>inary Trees1 are one of the common forms, i.e. trees !hereeach node has at most t!o children. 7or those of you for !hom this is ne!, note this isn1t ageneral grah. Trees aren1t suosed to loo back on themselves they "ust branch.

    ata ?ree a = ull oe a (?ree a) (?ree a)

    This is a relatively comlicated tye. t is a 1data1 tye, defined !ith the reserved !ord 1data1,like 19aybe a1 !as. t is also olymorhic like 19aybe a1 you can tell because the tye, 1Treea1, takes a tye variable. t has t!o data constructors, 1;ull1 and 1;ode1. 1;ull1 has no

    arguments and 1;ode1 has three. The !ay it is named indicates that it is a tree, and oninsection it is a binary tree, having t!o children in 1;ode1. 5o ho! !ould this !ork< 7irst,let1s !rite a value of this tye#

    t1 :: ?ree Intt1 = oe 2 (oe ull ull) (oe 5 (oe 4 ull ull) ull)

    f !e !ere to grah this tree, not including ;ull branches, it !ould look like this#

    2 < F 5

    < 4

  • 8/12/2019 Haskell Tutorial for C Programmers

    32/44

    The first node has both a 1left1 child and a 1right1 child, and the 1right1 child of the first nodealso has a 1left1 child. /et us revie! 1constructors1. n this e6amle 1Tree a1 is a tye, and1;ode1 and 1;ull1 are 1data constructors1 for that tye. $ data constructor, often simly called aconstructor, acts like a function that grous together ob"ects to form an ob"ect of a datatye.They only e6ist for tyes defined using 1data1 or 1ne!tye1. ;ote that they are different from

    tye constructors, such as 2 and 9aybe. ata constructors act like functions, and do notbelong in tye signatures. Tye constructors act like functions on tyes, and onl(belong intye signatures. They do not live in the same namesace, so often a 1data1 tye !ill have adata constructor of the same name out of convenience.

    Constructors are also used to 1deconstruct1 ob"ects of 1data1 tyes, like so#

    inrer@ist :: ?ree a -> &a'inrer@ist ull = &'inrer@ist (oe ite left ri6At) =

    inrer@ist left ++ &ite' ++ inrer@ist ri6At

    1in2rder/ist1 uses attern matching to determine !hich constructor its arameter uses.7urther, it 1deconstructs1 a value that uses the constructor 1;ode1 and binds its member valuesto the variables 1item1, 1left1, and 1right1, !hich are of tyes 1a1, 1Tree a1, and 1Tree a1,resectively. :e kno! these tyes because ;ode1s definition reads, G;ode a (Tree a) (Treea)G, and 1a1 is not further secified in this e6amle. 7or those of you unfamiliar !ith trees, 1t'1above is a 1binary search tree1, and evaluating 1in2rder/ist t1 !ill result in the follo!ing#

    *7ain> inrer@ist t1&,2,4,5'*7ain>

    Those values are in ascending order, since that is the definition of a 1binary search tree1. eadu on them if you1re not familiar !ith them already.

    There1s another funny thing about the definition of 1Tree a1. t1s recursive. t used 1Tree a1 todefine each child. @ou can do that in Haskell as !ell as C, but as usual, there1s a t!ist, andagain as usual it involves la?y evaluation. n CFCDD, to use a tye in its o!n definition, youmust declare a ointer to an ob"ect of its tye rather than including it directly. n Haskell,

    ointers aren1t used like that, so the tye is included directly, as in the tree e6amle. 5o !hatabout this definition#

    foo :: Int -> ?ree Intfoo n = oe n (foo (n - 1)) (foo (n + 1))

    t = foo 0

    :hat is the value of 1t%1< $nd !hat is its tye< The value of 1t%1 reIuires an infinite amount ofsace to store. The first fe! levels of the trees could be dra!n like this#

    0 < F -1 1 < F < F - 0 0

    < F < F < F < F

  • 8/12/2019 Haskell Tutorial for C Programmers

    33/44

    $nd so on. >ut the tye of 1t%1 is simle, and should be clear from the tye of 1foo1#

    t :: ?ree Int

    :hen you get an error message (not if ever, but w!enyou get an error message) that says

    Gcan1t do such-and-such, unification !ould result in infinite tyeG, it means that the tye!ould reIuire an infinite amount of sace to store. Tyically this haens !ith atternmatching on lists. n that case a careful check !ill sho! that something incorrect in the code!ould have resulted in nested lists infinitely dee, meaning a tye that looks like this#

    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    $nd so on. >ut back to 1t%1. ts tye is not infinite, even though its tye is defined recursivelyand t% has a value that, !hen evaluated, !ould reIuire infinite sace to store. >ecause its tyeis defined recursively, Haskell (and you) kno! that values of tye 1Tree a1 can contain other

    values of tye 1Tree a1. The fact that each value of tye Tree a !hich is 1in1 t% uses theconstructor 1;ode1 is not stored in the tye of t%, so the tye of t% is finite and Haskell can useit. $lso, multile values of tye 1Tree nt1 can e6ist, some infinite, some not, and they all havethe same tye. 2kay &a' -> &Int' -> asu@isteJ1 nus ini$es = su (ap (nus 99) ini$es)

    http://www.haskell.org/wikiupload/7/72/HaskellForC_Examples.tar.bz2http://www.haskell.org/wikiupload/7/72/HaskellForC_Examples.tar.bz2http://www.haskell.org/wikiupload/8/82/HaskellForC_Examples.ziphttp://www.haskell.org/wikiupload/8/82/HaskellForC_Examples.ziphttp://www.haskell.org/wikiupload/7/72/HaskellForC_Examples.tar.bz2http://www.haskell.org/wikiupload/8/82/HaskellForC_Examples.zip
  • 8/12/2019 Haskell Tutorial for C Programmers

    38/44

    su@isteJ nus ini$es = su U ap (nus 99) ini$es

    1[1 is a do-nothing oerator it1s only oint is to alter the recedence of the e6ressions on itsleft and its right. t takes t!o values as arameters and alies the first the the second. This is

    useless, mathematically, but it can let a rogrammer avoid arenthesi?ing lengthye6ressions. learned it from using H2en4/, since many of the state altering functions takeseveral lines of arameters.

    The second iece of synta6 is the effect of backIuotes, 1\1, !hich are belo! 1M1 on manykeyboards. :hen laced around a function !hich accets t!o arameters, backIuotes makethat function act like an oerator.

    printIs7eberJ1, printIs7eberJ :: (CQ a, AoB a) => &a' -> a -> I ()printIs7eberJ1 ites ite = if ele ite ites

    tAen puttr@n U (sAoB ite) ++ is a eber of tAe listelse puttr@n U (sAoB ite) ++ is ? a eber of tAe list

    printIs7eberJ ites ite = if ite VeleV itestAen puttr@n U (sAoB ite) ++ is a eber of tAe listelse puttr@n U (sAoB ite) ++ is ? a eber of tAe list

    1elem1 takes t!o arameters, a single item and a list of the same kind and returns True if thesingle item is resent in the list, other!ise 7alse. n the second definition(1rints9emberv%1), backIuotes are use to use \elem\ like an oerator bet!een its t!o

    arameters.

    could have !ritten my e6amles !ithout these e6tra synta6 niceties, but that !ould make

    them less like real code. f you1ve come this far, believe that you can handle it.

    The e6amles aren1t in order of imortance. 5ki around if you like, or skim the source codefor style hints. 5ome of the e6amles involve comlicated toics, but they are hoefullydocumented !ell enough that assing familiarity is sufficient.

    :.2 Part II0 Calculating Pi

    1i1 is a builtin constant in Haskell, as it is in many languages. This e6amle demonstrates

    some Haskell techniIues by calculating i in various !ays. The easiest !ay to use thise6amle is to load the source into 4HCi and notice ho! long it takes each value 1i'1, 1i%1,and 1i31 to evaluate the first time. The files#

    E6amlePiCalc.hs

    n Haskell, 1i1 is defined in the 17loat1 class here#

    The Prelude# the 17loat1 class

    9uch of the math in the code !as taken from this age#

    http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AFloatinghttp://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t%3AFloating
  • 8/12/2019 Haskell Tutorial for C Programmers

    39/44

    :ikiedia1s article GComuting PiG

    The values generated by the code differ slightly from the most accurate value ossible. n t!ocases, the last digit is slightly off because the math used involves rounding the last digit. nthe case of 1i'1, this is because greater accuracy is unattainable using that method !ithout

    e6cessive comutation.

    2nce one of the constants has been evaluated, it !ill not be reevaluated if reIuested a secondtime. @ou can see this in 4HCi by noting that 1i'1 takes several seconds or more to rint thefirst time, but virtually no time after that. This is an e6amle of la?y evaluation alied toconstants.

    :.3 Part III0 -erge'ort ariations

    This e6amle rovides the functions 1merge5ort'1, 1merge5ort%1, and 1merge5ort31 as !ell assome simle test lists 1list'1, 1list%1, and 1list31. The easiest !ay to use this e6amle is to loadthe source into 4HCi and try the different sort functions on various lists. $lso try the function1sort1 in ata./ist for comarison. The files#

    E6amle9erge5ort.hs

    This is not ractical code, since the default 1sort1 function is efficient for lists, but the variantsillustrate a lot of the basics of Haskell. The default sort function can be reached in sourcecode by utting Gimort ata./istG at the to and in 4HCi and Hugs by using G#m ata./istG.

    @ou have to load a module before a file in 4HCi.

    7or those unfamiliar !ith merge sort, the basic idea is that you sort t!o halves of a listsearately, then do a simle merge oeration the makes one sorted list from the t!o sortedhalves. Ho! do you sort the halves< >y running merge sort on them, too. This slittingcontinues until you get to a manageable number of items, in this case do!n to ?ero or one.Then you merge back together.

    The versions of merge sort here do not vary that behavior. :hat is changed is someotimi?ations that try to avoid as much recalculation as ossible. To slit a list in half, youneed its length. The first and simlest variant calculates that for every call, !hich arguably

    uses some redundant comutation.

    The second variant tries to avoid this redundancy by assing around the length of the list anddividing it by % at ever call. This !ould result in some slightly losided merges, but no realloss of efficiency there. The gains !ould robably out!eigh the loss.

    The third variant goes overboard and tries an otimi?ation that is likely !orse than the secondvariant. This is an e6amle of a good idea !hich needs close e6amination. The third variantforms t!o halves by lacing individual items alternately into t!o lists. This avoidsrecalculating the length !ith each call and avoids assing an integer and doing math !itheach call. Ho!ever, about as much !ork is necessary to slit the list in this manner as in the

    other methods, ossibly more.

    http://en.wikipedia.org/wiki/Computing_%CF%80http://en.wikipedia.org/wiki/Computing_%CF%80
  • 8/12/2019 Haskell Tutorial for C Programmers

    40/44

    :. Part I0 %egular 6)#ressions and *inite Automata0 $7er7iew

    $s said before, Haskell1s o!er only shines !hen it is used for larger ro"ects. This makes it

    difficult to demonstrate Haskell1s ability !ithout !riting code on toics that !ill beunfamiliar for some students. The smaller e6amles above and in the other sections of thetutorial are aimed at broad audiences, but such good e6amles are not necessarily availablefor more comle6 demonstrations.

    $t the risk of alienating some readers, have !ritten a comle6 e6amle covering regulare6ressions, finite automata, Haskell1s module system, and !riting your o!n monads. This isa big e6amle and it covers a lot of ground. The files involved are#

    E6Eto7$convert7$.hs

    E6Eto7$convert;7$.hs

    E6Eto7$convertE.hs

    E6Eto7$convertEv'.hs

    E6Eto7$convertEv%.hs

    E6Eto7$convertEv%monad.hs

    E6Eto7$convertEv3.hs

    E6Eto7$convertEv3monad.hs

    E6Eto7$e6amleTests.t6t

    E6Eto7$e6ecution.hs

    E6Eto7$main.hs

    E6Eto7$tyes.hs

    The code in this e6amle takes a string and arses it according to a subset of the P25standard for regular e6ressions (Es), converting it into a structure suited for testing inut.That structure is then converted to a non-deterministic finite automata (;7$) !hich !illaccet and re"ect eIuivalent inuts. 7inally, that ;7$ is converted to a deterministic finiteautomata (7$), although no great effort is made to minimi?e the number of states.

    f you don1t kno! !hat either regular e6ressions or finite automata are, these are covered indetail in any undergraduate comuter science education. f you are currently in school, you!ill get detailed instruction on them, robably soon. f not, these are toics you can learn atyour leisure. do not yet kno! if this e6amle can be understood !ithout a comlete

    kno!ledge of the material. Please send me feedback about that.

    :hether or not you are familiar !ith these concets, you can test the code !ith the e6amlesin E6Eto7$e6amleTests.t6t. 7irst you give a regular e6ression in P25 notation as aninut, then you reeatedly give strings to test against it. Kse Ctrl-C to Iuit.

    The statements are rinted as soon as each oeration is done, so if a statement fails to aear,that oeration !ent into an infinite loo. This occurs in some cases !ith the firstimlementation of running an ;7$ and is difficult to revent in any imlementation ofrunning a regular e6ression directly. 7or that reason, and because 7$s can be e6ecutedmore Iuickly, in ractice Es (and ;7$s) are converted to 7$s before use. 9yimlementation uses a counter to test for deely recursing e6ecution so can return a valueindicating failure.

  • 8/12/2019 Haskell Tutorial for C Programmers

    41/44

    :.+ Part 0 %egular 6)#ressions and *inite Automata0 T(#es

    The 1tyes.hs1 file for this e6amle rovides the tyes used in the rest of the files. n addition,

    the module rovides functions that validate members of those tyes and functions !hichcomute useful information from members of those tyes. This is the only module !hichdoes not include any other modules from the e6amle. 7iles#

    E6Eto7$tyes.hs

    The imort statements in this file (and the rest) do not bring into scoe everything from thestandard modules they imort. nstead, they only include the functions and tyes used in thecode. oing this hels track !hat functions are used !here and revents accidental clashes orsimilarities bet!een names.

    The comments in this file also include a summary of the P25 rules imlemented.

    :., Part I0 %egular 6)#ressions and *inite Automata0 'tring to %6 and

    -onads

    The base file for this art of the e6amle includes and re-e6orts three functions. There is onefor each version imlemented of the method to convert a string to the P25 regulare6ression that it reresents. 7iles#

    E6Eto7$convertE.hs

    E6Eto7$convertEv'.hs E6Eto7$convertEv%.hs

    E6Eto7$convertEv%monad.hs

    E6Eto7$convertEv3.hs

    E6Eto7$convertEv3monad.hs

    The first method, imlemented in 1convertEv'.hs1, is a set of functions !hich !ork on theinut string. They ass it around along !ith the ieces of regular e6ressions underconstruction. There is nothing !rong !ith this method, and in fact only added the othermethods as a final touch to the e6amle. Ho!ever, there is a lot of otential for mistakes!hen !riting the code, because the recisely correct string must be assed for!ard,simulating using u the right amount of the inut.

    This 1assing for!ard1 nature made the conversion suitable for reimlementation as a 9onad.=ersions % and 3 of this conversion sho! ho! you can make your o!n monad. @ou createthe tye, not an intuitive task !hen you need to carry a state. @ou then !rite the instancedeclaration, the accessor functions, and functions !hich comose those accessors.

    :hy use monads for this task< ;ote the tyes of the recursive functions#

    $onJertMCouter1 :: trin6 -> 7#Me6Cp -> 7a#be (7#Me6Cp, trin6)$onJertQuarelo$81 :: trin6 -> 7a#be (7#Me6CpIte, trin6)

    $onJertuberlo$81 :: trin6 -> 7a#be (Int, Int, trin6)

  • 8/12/2019 Haskell Tutorial for C Programmers

    42/44

    n each case, the inuts are returned, modified. This is a te6tbook case for creating a monad,or !ould be if any book e6isted !ith that hint. Ksing a monad lets us searate our changes tostate, assed for!ard to the ne6t function called, from our return values, assed u!ard to thecalling function.

    5ince a 5tring is assed for!ard in every case, that !ill be the monad1s state, its internalvalue. The rest of the data !ill be normal return values. The functions have almost e6actly thesame structure, but the code is clearer.

    The instance !as very hard for me to !rite. There are t!o issues, the first being that thesynta6 for nstance declarations is tricky to find. The second is that, even armed !ith the tyeof (UUO), the functions are difficult to !rite. /et1s analy?e them. Here1s !hat 4HCi saysabout (UUO)#

    /relue> :t (>>=)(>>=) :: (7ona ) => a -> (a -> b) -> b

    $t least !e can tell that it has t!o arameters, one of tye 1m a1 and one of tye 1(a -U m b)1.The immediate Iuestion, if you can understand the tyes, is, G:hy is the monad tye assed atye variable as if it is a tye constructoroth files make use of a searate file to store their tyes. The e6ort list

    for those sub-modules secifically fails to e6ort the constructor for the monad tye. Thisforces the functions outside that sub-module to only modify and use the monad using the

    http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htmhttp://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm
  • 8/12/2019 Haskell Tutorial for C Programmers

    43/44

    e6orted accessor and run functions. This is done to make the data tye abstract and keecode clean.

    t is !orth noting that even !ith the data tye in a searate file, the code is longer !henimlemented using a 9onad. The synta6 of monads is slightly more verbose, and can create

    some a!k!ardness in smaller ro"ects such as this. $s a ro"ect scales in si?e, the gainsincrease !hen using monads in cases for !hich they are aroriate. 9any of the gains comefrom lack of errors in carrying state for!ard, !hich is most of the oint in the first lace.

    :.: Part II0 %egular 6)#ressions and *inite Automata0 Con7ersion and

    6)ecution

    The remaining conversion files for this e6amle imlement some standard algorithms forconverting Es to ;7$s and ;7$s to 7$s. The code is comle6 and sho!s a lot of the

    o!er of Haskell. The ma"ority of the source code is comments rather than code. n addition,the code !as !ritten as clearly as ossible rather than focusing on brevity. Hoefully, this!ill hel the reader follo! along. 7iles#

    E6Eto7$convert7$.hs

    E6Eto7$convert;7$.hs

    The e6ecution file for this e6amle uses multile methods to test inut strings against theresulting structure from each oint in the conversion rocess. The key distinctions are thatsome methods track the set of reachable states simultaneously, acceting !hen any reachable

    state !ould accet, and other methods make a searate recursive call for all branches. Thebranching method is rone to infinite loos. The fact that Es and ;7$s branch, !hile theend result, 7$s, do not branch, illustrates !hy this conversion is usually erformed. 7iles#

    E6Eto7$e6ecution.hs

    n the main rogram for this e6amle, these e6ecution methods are ordered and dislayed.E6tensive use is made of basic oerations in the 2 monad, and this file can serve as ane6amle for that as !ell, articularly the need to flush buffers after !rites !hich do not endin a ne!line. 7iles#

    E6Eto7$main.hs

    :.; Part III0 'ol7ing 2C/*s in Linear Time

    The final e6amle, currently, is an abbreviated demonstration of list comrehensions and the1data1 data tye declaration. The rogram solves boolean eIuations in con"unctive normalform !ith t!o variables each, also called %C;7. This is !idely kno!n as a secial case of the

    ;P-Hard C;7 roblem. The files#

    E6amle%C;7.hs

    The source code for this e6amle indicates several !ays to e6and on it.

  • 8/12/2019 Haskell Tutorial for C Programmers

    44/44

    Eric Etheridge, ethersonZyahoo.com