Sei sulla pagina 1di 44

Haskell Tutorial for C Programmers

Haskell Tutorial for C Programmers, by Eric Etheridge version 3.0 - lease increment !ith ma"or u dates original author# Eric Etheridge last ma"or u date by the original author# $ugust %&, %0'' year of original release (on old haskell.org site)# %00*

Contents
+hide,

' -ntroduction o '.' $bstract o '.% .o!nloads o '.3 /icense o '.0 This Tutorial1s Pur ose and 2ther 2nline 3eferences '.0.' 4HC and Hugs '.0.% The 4entle -ntroduction to Haskell '.0.3 Tour of the Haskell 5ynta6 '.0.0 The Prelude 7ile '.0.* 4HC Heirarchical /ibraries '.0.8 9onads for the :orking Haskell Programmer o '.* Preface and 5tyle ;otes % 5ection -# :hat the Heck is 4oing 2n< o %.' Part -# Haskell1s 2ddity o %.% Part --# -n ut and 2ut ut o %.3 Part ---# =ery >asic -ntro to Ty es o %.0 Part -=# Haskell1s /ists and /ist Com rehensions o %.* Part =# 9aking 5ense of 1fibs1, and :hy /a?y Evaluation is -m ortant 3 5ection --# To!ards 7unctions o 3.' Part -# The 2rder of 2 erations as a Programmer o 3.% Part --# 7unctions, >ut 3eally a 5idetrack to Ty es o 3.3 Part ---# 9ore Ty es, >ecause Haskell -s 1Polymor hic1 o 3.0 Part -=# 7unctions $lready 0 5ection ---# ;o! /et1s 3eally :rite 7unctions o 0.' Part -# .id @ou Take That >reak< Here $re Patterns o 0.% Part --# $fter Patterns, 4uards o 0.3 Part ---# 1-f1 o 0.0 Part -=# -ndention 5ynta6 o 0.* Part =# $nd /ambda 7unctions o 0.8 Part =-# Polymor hic Ty es and Ty e Constructors o 0.A Part =--# The -2 9onad o 0.& Part =---# .issecting the -2 E6am le * 5ection -=# Haskell and @ou o *.' Part -# :here $re the 17or1 /oo s< o *.% Part --# 3emember /a?y Evaluation< -t1s 5till There o *.3 Part ---# The Point(s)

8 5ection =# 7inal Commentary o 8.' Part -# :hy is 13eferential Trans arency1 :orth $nything< o 8.% Part --# 7eedback and ;otes o 8.3 Part ---# 3anting A 5ection =-# E6tended E6am les o A.' Part -# -ntro to E6am les o A.% Part --# Calculating Pi o A.3 Part ---# 9erge5ort =ariations o A.0 Part -=# 3egular E6 ressions and 7inite $utomata# 2vervie! o A.* Part =# 3egular E6 ressions and 7inite $utomata# Ty es o A.8 Part =-# 3egular E6 ressions and 7inite $utomata# 5tring to 3E, and 9onads o A.A Part =--# 3egular E6 ressions and 7inite $utomata# Conversion and E6ecution o A.& Part =---# 5olving %C;7s in /inear Time
o

A.B Part -C# -n Closing

1 Introduction
1.1 Abstract
9any eo le are accustomed to im erative languagues, !hich include C, CDD, Eava, Python, and Pascal. 7or com uter science students, Haskell is !eird and obtuse. This tutorial assumes that the reader is familiar !ith CFCDD, Python, Eava, or Pascal. - am !riting for you because it seems that no other tutorial !as !ritten to hel students overcome the difficulty of moving from CFCDD, Eava, and the like to Haskell. - !rite this assuming that you have checked out the 4entle -ntroduction to Haskell, but still don1t understand !hat1s going on. Haskell is not 1a little different,1 and !ill not 1take a little time.1 -t is very different and you cannot sim ly ick it u , although - ho e that this tutorial !ill hel . - am going to ut many auses in this tutorial because learning Haskell hurt a lot, at least for me. - needed breaks, and my brain hurt !hile - !as trying to understand. Haskell has both more fle6ibility and more control than most languages. ;othing that - kno! of beats C1s control, but Haskell has everything C does unless you need to control s ecific bytes in memory. 5o - call Haskell o!erful, rather than "ust 1good.1 - !rote this tutorial because Haskell !as very hard for me to learn, but no! - love it. GHaskell is hardHG G@ou can1t !rite code the !ay - kno! ho!HG G9y brain hurtsHG GThere aren1t any good referencesHG That1s !hat - said !hen - !as in college. There !ere good references, but they didn1t cover the real roblem# coders kno! C.

This abstract !as ieced together by 9ark Evans, here, from my o!n !ork. - have had no contact !ith 9ark Evans, but since he did1t contact me !hen he editted together this abstract from my !ork and osted it on lambda-the-ultimate, - doubt he1ll care that -1ve taken that edit and used it as my abstract here. -f he !ishes, he may contact me regarding the legal status of this !ork. 7or no!, - assume - still hold the co yright on all of it, including the abstract (released in the license for this site).

1.2 Downloads
-n the former form of this tutorial, - had a ?i ed version of the html files available at this oint. Ho!ever, this !iki rovides a G rintable versionG button and the tutorial is no! be one long age (!hich may be a oor design choice, !e1ll see). -n addition, a bundled version might Iuickly become out of date from minor corrections by site atrons. Therefore, it doesn1t seem necessary at the moment to include a ?i ed bundle of the tutorial te6t. Here are the source files and te6t for all e6am les for this tutorial, including all those in the sections and the large e6am les at the end, ?i ed using b?i %# b?i % of sources, %&J, and ?i ed as a ?i # ?i of sources, 03J. 5ources for the in-te6t e6am les in the coming sections are given in the follo!ing files#

E6am le5ectionsCode.hs E6am le5ectionsTry.t6t

-f you don1t have b?i %, you can get the latest version at !!!.b?i .org.

1.3 License
The original form of the tutorial !as available under a Creative Commons /icense, s ecifically $ttribution-5hare $like 3.0. That license still a lies to any form do!nloaded or read !hile that version !as available. This !iki reIuires submitted !ork to be sub"ect to a s ecific license, so this !ork is no! available under this sim le ermissive license. - !ould still refer some attribution if the !ork !as used !holesale.

1. T!is Tutorial"s Pur#ose and $t!er $nline %eferences


9any eo le are accustomed to im erative languagues, !hich include C, CDD, Eava, Python, and Pascal. -n fact, most languages in common usage are im erative, other than /-5P, 5cheme, 9/, and 2Caml. 7or com uter science students in high school or early college, it is virtually guaranteed that Haskell is !eird and obtuse. - first encountered Haskell in the classroom !hen - !as a freshman at KT $ustin, and then in another class at KT t!o years later. - !as only familiar !ith CFCDD, Pascal, and L>$5-C, and all of the Haskell tutorials and books seemed to assume more of my education. This tutorial assumes that the reader is

familiar !ith CFCDD, Python, Eava, or Pascal. This tutorial is s ecifically for students of com uter science, eo le in their first fe! years of college, or even in high school. - am !riting for you because it seems that no other tutorial !as !ritten to hel students overcome the difficulty of moving from CFCDD, Eava, and the like to Haskell. 1. .1 &HC and Hugs To learn and use Haskell, you should install 4HC, and erha s Hugs. 4HC is the Gde facto standardG com iler for Haskell, and almost all ro"ects in Haskell use it. The Hugs inter reter is a sim ler tool that !ill let you lay around and learn. 5tart !ith Hugs if you are having trouble using 4HC. 4HC also shi s !ith 4HCi, G4HC interactiveG, !hich is a command line inter reter much like Hugs, but no 4K-. 4etting these rograms is easy. -f you use .ebian, 4HC and Hugs are ackages. 7or everyone else, the home ages are here# htt #FF!!!.haskell.orgFghcF htt #FF!!!.haskell.orgFhugsF 1. .2 T!e &entle Introduction to Haskell - !rite this assuming that you have checked out the follo!ing tutorial, the 4entle -ntroduction to Haskell, but found that you still don1t understand !hat1s going on# htt #FF!!!.haskell.orgFtutorialF 1. .3 Tour of t!e Haskell '(nta) The 4entle -ntroduction to Haskell is a good reference for basic synta6. -n this tutorial !e !ill ski most synta6 details until later. 7irst !e !ill cover defining functions in Haskell and !hy it is central to the language. 7or more synta6 details, here is another tutorial, the Tour of the Haskell 5ynta6, !hich has much more s ecific information# htt #FF!!!.cs.ute .eduFcheonFcs3380F agesFhaskell-synta6.html @ou should look through the Tour, since it describes the a ro riate synta6 for most of the things - discuss. The Tour is useful because you can understand it !ithout kno!ing everything about Haskell. 3eading these can hel you before, after, or during this tutorial. 1. . T!e Prelude *ile 2ne of the best references is the source code for the Prelude, !hich is the file GPrelude.hsG. This file holds the code for all of the general- ur ose functions in the Prelude module. -f any function sho!s u that you don1t understand, you can look u its definition in source code and figure out !hat it1s really doing. This is a very good ractice for those unfamiliar !ith general Haskell use. There are (at least) three !ays to get a co y of the Prelude.hs file. -f you do!nload and install Hugs, Prelude.hs !ill be in the libraries directory. - do not think that 4HC shi s !ith the uncom iled library sources. @ou can do!nload a source version of 4HC from its do!nload age. @ou may be able to find a g?i ed co y in the ghc GlibsrcG .ebian ackage.

1. .+ &HC Heirarc!ical Libraries $nother im ortant resource is the 4HC Hierarchical /ibraries documentation. The data ty es and functions of every module are defined here, including the Prelude. :henever you use a library function, you1ll !ant to refer to these to find the module and s ecific usage. $ll the standard modules are !ell documented. -f your 4HC installation includes the docs, these !eb ages are also on your local machine. htt #FF!!!.haskell.orgFghcFdocsFlatestFhtmlFlibrariesFinde6.html 1. ., -onads for t!e .orking Haskell Programmer :hen - !as !orking on the large e6am les that included monads, - used a lot of hel from here# htt #FF!!!.engr.mun.caFMtheoF9iscFhaskellNandNmonads.htm

1.+ Preface and 't(le /otes


- am not !riting a Haskell reference. This is a tutorial designed to take someone having trouble understanding Haskell and hel them. This tutorial is for eo le !ho, like me, needed to learn enough conce ts to understand the code covered in a classroom. Haskell allo!s things to be done easily and clearly, but it is not easy or clear, and it can be e6tremely challenging for a novice. @ou cannot ick u Haskell code and understand it. :hat - have attem ted to !rite is a tutorial that covers the common as ects of Haskell that are the most obtuse. $s the tutorial rogresses, one thing should become clear about Haskell# its real o!er comes into lay !hen you attack difficult roblems. >ecause of this, - use some difficult roblems in this tutorial. .on1t !orry if you don1t understand the solutions after reading the tutorial once. Haskell is not a toy language, and even a moderately si?ed set of functions !ill include several of Haskell1s com licated tools all !orking together. This has left educators !ith a dilemma# do - use ridiculously sim le code in order to cover a single to ic at once, or do - use something actually useful and try to e6 lain all the ieces and ho! they all fit together< 9any tutorials and lessons have chosen the former, but - refer the latter. That means that each e6am le reIuires a lot of e6 laining. 2ften conce ts must be e6 lained once in e6tremely sim listic terms, and then e6 lained again later after other related to ics have also been briefly discussed. $s you read this tutorial, remember this# Haskell1s real o!er is the fact that 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 Haskell source code and libraries, and !hat - learned in college. Haskell rograms tend to be short, but !ide. - recommend using descri tive variable names, even for indices and so forth.

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

2.1 Part I0 Haskell"s $ddit(


To begin, Haskell has no u date o erator. -f that sentence did not make sense, then lease kee reading, because this tutorial !as !ritten !ith you in mind. >y 1u date o erator1, - mean that the follo!ing does not ha en in normal Haskell#
int a a := 4 print a a := 5 print a > 4 > 5

The above rogramming style, i.e. 1making a variable, utting data in it, using it, then re lacing the data in it, using it again1 does not ha en in normal Haskell. Those of you !ho have used /-5P or 5cheme !ill be familiar !ith this conce t, but - am sure that the rest of you are robably baffled. Here is ho! Haskell !orks, again in seudo-code#
print a int a a = 5 > 5

or
int a a = 5 print a > 5

The order of these actions does not matter. There is also a reason that the first e6am le used 1#O1 and the second e6am le used 1O1. -n 1im erative1 languages, storing data is an o eration, and it ha ens in a seIuence. -n 1functional1 languages like Haskell, the eIual sign means an e6act definition. -n other !ords, each variable is eIual to its value not only after the assignment 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 everything is hardcoded< :ouldn1t - have to define every variable !ith its correct value as - coded< -sn1t 1com uting1 values the !hole oint of a 1com uter1<G $nd you !ould be rightP kno!ing results ahead of time !ould make com uting !eird. The 1redeeming1 feature of Haskell is that you don1t need to store data to return a result. - am going to ut many auses in this tutorial because learning Haskell hurt a lot, at least for me. - needed breaks, and my brain hurt !hile - !as trying to understand. /et1s look at that statement again# you don1t need to store data to return a result. -1ll illustrate. Here is an e6am le of a function in C#
int foo (int bar) {

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

The im ortant art is the e6 ression 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 could state the follo!ing# GThe value of foo(6) is eIual to (6 Q '0 D 0).G 2r, more sim ly, Gfoo(6) O 6 Q '0 D 0G. - kno! you1re saying, G9ost functions aren1t that sim le.G That is true, but bear !ith me. Haskell has much more o!erful tools for !riting functions than most other languages, and a lot of com licated o erations look this sim le in Haskell. The key to using those tools !ill be changing the !ay you think from "make data2 t!en alter it" to "define a function t!at would return t!e result2 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 and CFCDD that many conce ts only make sense in con"unction !ith others. - need to cover the basics of several conce ts before - can e6 lain each of them fully. 9oving on, the Iuestion on everybody1s mind is robably either, GHo! does -F2 !ork<G or G:hat are these tools<G -2 is one of the com licated arts of Haskell, and later -1ll describe ho! it !orks. - !ill also describe a sim le frame for rogramming !ith 4HC. Kntil then, use 4HCi or Hugs to try the e6am les. They have an interactive rom t !here you ty e in e6 ressions, like a function lus its arameters. Then they rint the evaluated result. $lso, variable bindings such as 1a O 01 hang around !hile you1re using Hugs and 4HCi, so my e6am les should !ork "ust fine. To !rite your o!n functions, you need to !rite a Haskell source file and load it first. Ksing 4HC itself reIuires kno!ing some of Haskell1s more com licated tools, so !e1ll ut off learning those until !e need 4HC. To use Hugs and 4HCi !ith your o!n functions, you have to !rite a Haskell source file and load it into the inter reter. 4enerally, this !orks as follo!s# '. %. 3. 0. *. 2 en a te6t editor and !rite Haskell code. 5ave that code as a file !ith the e6tension 1.hs1, for instance, 1test.hs1. :ith the source file in the current directory, run Hugs or 4HCi. -n Hugs or 4HCi, at the rom t ty e 1#l test.hs1. That1s a lo!ercase 1/1. 5ource code that needs modules, say .ata.9aybe, should include 1im ort .ata.9aybe1 at the to .

;ote that the module 1Prelude1 is automatically im orted. The Prelude module covers most basic elements of the language.

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


9oving on again, let1s talk about tools. Haskell1s greatest strength lies in the o!er a rogrammer has to define useful functions easily and clearly. Here is our earlier e6am le from 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, e6ce t for the ty e#


foo :: Int -> Int

The ty e reads, Gfoo is of ty e -nt to -ntG, meaning that it takes an -nt and returns an -nt. Together, you !rite#
foo :: Int -> Int foo bar = bar * 10 + 4

.efining functions and ty es is the ma"ority of the !ork in Haskell, and usually they reIuire eIual amounts of time. Haskell has a variety of !ays to define functions. - feel that the tutorials mentioned reviously do not adeIuately introduce these !ays, so !e !ill discuss them in detail later once !e have some tools under our belt.

2. Part I30 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. 7or almost all im erative languages, the most useful structure is the $rray, a randomly accessible seIuence of values usually stored in order in memory. Haskell has arrays, but the most-used ob"ect in Haskell is a /ist. $ list in Haskell is accessible only at the front, and is not stored in order 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 to com ute the fibonacci numbers (starting !ith ?ero)#
int fib (int n) { int a = 0, b = 1, i, te p; for (i = 0; i ! n; i++) { te p = a + b; a = b; b = te p; } return a; }

This is fine for com uting a articular value, but things get ugly !hen you !ant to create the seIuence#
int * fib"rra#(int n) { int * fibs; fibs = (int *) allo$((si%eof int) * n); for (i = 0; i ! n; i++) { fibs&i' = a; te p = a + b; a = b; b = te p; } return fibs; }

:hen - say 1get ugly1, - mean that something is included in that function !hich shouldn1t be there# the si?e of the list. The fibonacci seIuence is infinite, and the code above does not re resent 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 com ute a single fibonacci value, can be !ritten as follo!s#
fib :: Int -> Int fib n = fib(en 0 1 n fib(en :: Int -> Int -> Int -> Int fib(en a b n = $ase n of 0 -> a n -> fib(en b (a + b) (n - 1)

This is a slight im rovement over the C code, but not much. ;ote that the ty e of fib4en is G-nt 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. 3ecursion is every!here in Haskell. 9ost of your 1loo ing1 functions !ill involve recursion instead. The real im rovement 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 0, then %, then 8, etc. The 1#1 o erator is used to com ose a list by sticking a value on the front (left). 7or instance# te p = 1 : & 4, *, 5 ' is the list + ', 0, %, * ,. That means that in the above code, fibs is a list of -nt, and its first t!o values are ?ero and one. That1s good so far. $t least the first t!o values of 1fibs1 !ill be right. The ne6t art definitely looks !eird. -t1s a tool found in Haskell called a 1list com rehension1. -n Part --, said that instead of making s ace and then filling it !ith the right values, you can define the right values. Here1s that sentence, restated for list com rehensions# G@ou can define the

values of the list rather than make s ace and then fill them in.G /ist com rehensions !ork like so#
& fun$ - ) - !- list, bool.un$ - '

This e6 ression makes a ne! list. -n the middle, there1s a 1list1, and it s its out values called 6. These are the values of the list in order. -f 1bool7unc 61 is True, then 6 !ill get used in this ne! list. ;o bool7unc is in the 1fibs1 e6am le, but - include it here because it can also be e6tremely handy. $ssuming 1bool7unc 61 !as true, 1func 61 a lies some function to the value of 6, and the result is then ut ne6t in line in the final result. Here1s an e6am le of a list and its use in some list com rehensions, co ied from using 4HCi#
/relu0e> let nu s = & 4, *, +, 1, 5, 11 ' /relu0e> & - + 1 ) - !- nu s ' &5,2,,,3,+,1*' /relu0e> & - * - ) - !- nu s, - ! , ' &1+,4,2+,*5' /relu0e> & * * - ) - !- 3 : 1 : nu s ' &11,*,1,4,1*,1+,10,**' /relu0e> & 45trin64 ) - !- nu s, - ! 5 ' &45trin64,45trin64' /relu0e>

;ote that the order !as reserved in each case. This is very im ortant for our e6am le. $lso note that the ty e of the list com rehension !as not necessarily the ty e of nums, nor did 6 actually have to be used in the function. /et1s return to 1fibs1.

2.+ Part 30 -aking 'ense of "fibs"2 and .!( La5( 67aluation is Im#ortant
:e !ere !orking on a definition for the list of 7ibonacci numbers. Here is the e6am le again#
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 more e6 ressive ty e system than most other languages. $s in Python, 1(a, b)1 is a tu le, meaning t!o values stuck together. -t1s a convienent !ay to store and ass multi le values, much more so than structs. Eust add arentheses and enough commas, and you ass the grou of values around as you lease. The only trick is that Haskell e6 ects you to be consistent, and that means having the right ty e. The code adds 1a1 and 1b1 together to get a number in the 7ibonacci seIuence, so !e kno! that1a1 and 1b1 are integers. Clearly, 1(a, b)1 is of ty e 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?i fibs (tail fibs)1 is of ty e 1+(-nt, -nt),1, a list of %-tu les of an -nt and an -nt. 9ore clearly#
%ip fibs (tail fibs) :: &(Int, Int)'

@ou can use 4HCi and Hugs to rint these ty es. The 1#t1 command, follo!ed by a variable or function, !ill rint its ty e. The follo!ing is at the 4HCi rom t !ith the e6am le file that includes the fibs function loaded#
*7ain> :t %ip fibs (tail fibs) %ip fibs (tail fibs) :: &(Int, Int)' *7ain>

5o !hat is 1?i 1< -ts ty e and general meaning are given here# The Prelude, section# Ri ing and Kn?i ing /ists 1?i 1, as its name some!hat im lies, takes t!o lists and 1?i s1 them together, returning a list of tu les, !ith the left member of each tu le being an item from the first (left) list, and like!ise for the right.
/relu0e> %ip & 1, 2, +, * ' & 40u$84, 40u$84, 40u$84, 46oose4 ' &(1,40u$84),(2,40u$84),(+,40u$84),(*,46oose4)' /relu0e>

$nd !hat about 1(tail fibs)1< 1tail1 is a retty straightfor!ard function# it cho s off the first item of a list and returns the remainder. That statement can be slightly misleading. 1fibs1 doesn1t get altered by using 1tail1 on itP as - said before, Haskell doesn1t have an u date o eration. -nstead, 1tail1 "ust com utes the ro er result and returns it, rather than altering 1fibs1 itself.
/relu0e> tail & 10, *0, 20, 40, 50 ' &*0,20,40,50' /relu0e>

:ell, that makes it seem like 1?i fibs (tail fibs)1 robably has the right ty e, but !hat is it<
fibs :: &Int' fibs = 0 : 1 : & a + b ) (a, b) !- %ip fibs (tail fibs)'

The first aramater to ?i is 1fibs1, !hich is the list defined by the e6 ressionH :hat the heck< Can you do that< @es, you can. 5ee, 1fibs1 is the entire list, including the 0 and ' at the beginning. 5o the first t!o tu les in the list created by the ?i function !ill have a 0 and then a ' on their left. 5o !hat is 1?i fibs (tail fibs)1< :ell, the first value is definitely (0, '). :hy< >ecause the first item in fibs is 0, and the first item in (tail fibs) is ', the second item in fibs. 5o !hat1s the second value in ?i fibs (tail fibs)< -t1s (', '). :here did the right hand ' come from< -t1s the third value in fibs, !hich !e "ust com uted. The first value of ?i fibs (tail fibs) is (0, '), !hich is 1(a, b)1 in the list com rehension, and so the first value in that com rehension is 0 D ', or '. That is also the third value in fibs, etc. .id you catch all that< The definition of fibs is evaluating itself !hile it is com uting itself. 5o !hy didn1t some sort of error ha en because of undefined values< The trick to all of this is Haskell1s la?iness. $lso, the evaluation is al!ays one ste behind the com utation, so evaluation can al!ays roceed e6actly as far as needed for the ne6t com utation. 7inally, this list is infinite. 2f course, no com uter can hold an infinite amount of data. 5o ho! much is really there< The ans!er is sim le# until you read some values from fibs and rint them, there1s only the 0 and the ', lus the function to generate more of the list. $fter you read

some, fibs !ill be evaluated to that oint, and no further. 5ince fibs is defined globally, it !ill remain defined in memory, making reading further values very Iuick. Try this !ith Hugs or 4HCi and you see1ll !hat - mean.
fibs fibs fibs fibs fibs fibs fibs ta8e 99 99 99 99 99 99 99 10 * 4 20 20 + *0 20 fibs

1HH1 is the 1inde61 o erator for lists in Haskell. -t !alks do!n the list and returns the nth item, ?ero-inde6ed like CFCDD and Python. 1take '0 fibs1 !ill return the first '0 values of fibs. >e careful, fibs has infinite length. -f you "ust ty e 1fibs1, the out ut could go forever. $nd !hy does the list only get evaluated as far as you rint it< Haskell is 1la?y1, meaning that it doesn1t do !ork that it doesn1t have to. C rogrammers kno! that the boolean o erators 1SS1 and 1TT1 are 1short-circuit1, meaning that the right hand side is not evaluated unless it1s needed. This allo!s for all kinds of neat tricks, like not dereferencing a null ointer. T!e entire language of Haskell !as t!is s!ort8circuit be!a7ior2 including t!e functions t!at (ou write (ourself. This sounds strange, and !ill become even more im ortant !hen !e get to Haskell1s tools. This also brings us to one of the other odd things about Haskell# It is often easier to code t!e general definition for somet!ing t!an to write a function t!at generates a s#ecific 7alue. This is one of those things you have to get used to, and you !ill robably come back to it again. $nd again. :ell, give yourself a at on the back. -f you got all that, or at least you !ill after laying around in Hugs, then you understand about half of the common usages of Haskell. 3eady for the other half< 9aybe take a break, and lay around a bit in Hugs or 4HCi.

3 'ection II0 Towards *unctions


3.1 Part I0 T!e $rder of $#erations as a Programmer
$ rogramming note for recursive functions and Haskell# Concerning the fib F fib4en e6am le here#
fib :: Int -> Int fib n = fib(en 0 1 n fib(en :: Int -> Int -> Int -> Int fib(en a b n = $ase n of 0 -> a n -> fib(en b (a + b) (n - 1)

:hen - !as !riting this e6am le, - !rote the ty e of fib first, then the ty e and definition of fib4en, then finally the definition of fib. 7or those of you !ho are not accustomed to !riting recursive functions, Haskell rogramming often reIuires them. 2ften these recursive functions need subsidiary functions, !hich either 1frame1 the main o eration of recursion, or erform a sim le task that kee s the main recursion function clean. -n either case, the subsidiary functions can be !ritten later, after the ma"or recursive o eration is clearly defined including end conditions. -n general, it is a good idea to concentrate on the most crucial as ect of a iece of code !hen rogramming, but Haskell1s design greatly reinforces this. The definition of subsidiary functions, such as the 1setu 1 !here fib calls fib4en !ith arameters 10 ' n1, can !ait until the function itself has been !ritten. This is true even though the ty e of fib !as obvious from the beginning. /ike!ise, Haskell makes !riting trivial functions like that so Iuick that they can generally be ignored !hile thinking about the larger icture. These things are likely to change the !ay that you code, and robably in a good !ay.

3.2 Part II0 *unctions2 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 com are CFCDD to Haskell. -n C, a function is a seIuence of commands that have their o!n names ace, are called during e6ecution and assed arameters, inherit the names ace of the sco e in !hich they are !ritten, and return a value to their caller. -n Haskell, most of that is true, e6ce t of course functions in Haskell are not seIuences of events, but e6 ressions and definitions. There is a ma"or difference bet!een C and Haskell, ho!ever, and it concerns the amount of fle6ibility that functions have. -n C, functions take arameters and return a single value. :e1ve already seen that Haskell has many !ays to grou values, like several other languages. The t!o most common of these are lists and tu les, and these can be the return ty e from a function. To sum them u , in Haskell lists are variable length and hold values of the same ty e, and tu les are fi6ed length and can hold values of different ty es. Here is an e6am le of a function ty e that returns a tu le#
split"t :: Int -> &a' -> (&a', &a')

1s lit$t1 takes an -nt and a list and returns a tu le. The left value in the tu le is the first n values in the list, and the right value is the rest of the list, !here n is the first arameter. This function is in the Prelude, and its descri tion can be found here# The Prelude, section# 5ublists :e1ve already seen lists in a ty e#
fibs :: &Int'

5ince the fibonacci numbers gro! ra idly, but 1-nt1 is 3%-bit, it !ould robably have been better to use 1-nteger1, Haskell1s built-in infinite- recision integer storage. fibs ## +-nteger, $nd this is a function ty e. 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 return numbers com rising the fibonacci seIuence. That kind of logic is !hat lets Haskell1s com ilers roduce code !hich runs Iuickly and lets Haskell rogrammers !rite code efficiently.

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


-t1s time for a brief +not so brief, digression about ty es. $s you1ve noticed, the trend seems to be to call everything a 1function1. $nd that1s true. Take 101 for e6am le. :hen you use a number 101 hardcoded into your code, it looks to you like the number 0. >ut !hat is it to Haskell< Ty e 1#t 01 into Hugs or 4HCi. :hat do you get< @ou get some !eird "unk#
/relu0e> :t 4 4 :: (:u t) => t /relu0e>

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 ty e given is read as follo!s# Gfour is of ty e 1t1, !here 1t1 is in the 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 im ortant 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 ty es. 7or instance, addition and multi lication in CFCDD are overloaded, allo!ing the follo!ing combinations to occur#
int a = 4, b = 5; float - = *;5, # = ,;0; $out $out $out $out $out $out $out $out !! !! !! !! !! !! !! !! a a # b b # + + + + * * * * b; #; a; #; a; -; b; #; <<3 <<11 <<11;0 <<3;5 <<*0 <<1*;5 <<25;0 <<1,;5

-n CFCDD, this is accom lished by defining all of the follo!ing overloaded definitions for 1D1 and 1Q1#
operator+ operator+ operator+ operator+ (int, int); (int, float); (float, int); (float, float);

operator* operator* operator* operator*

(int, int); (int, float); (float, int); (float, float);

The C com iler icks the a ro riate ty e at com ile time. The key distinction bet!een olymor hism and overloading is that in CFCDD, !hich uses overloading, each function above must be !ritten se arately. -n CFCDD, any function besides those above that uses either an int or a float must s ecify !hich one it e6 ects, or must itself be overloaded. This bring us to the idea of classes. 7or !hat ty es is 1D1 defined in CFCDD< -t is ossible to overload the o erator for ne! ty es defined by a user, but those ne! ty es !ill not be interchangeable !ith ints, floats, or other numeric ty es. :hat this means is that e6isting sort functions such as merge5ort and Iuick5ort !ould need to be re!ritten to sort values of the ne! ty e. -n constrast, here is the ty e of merge5ort in Haskell#
er6e5ort :: =r0 a => &a' -> &a'

:hat is going on< $gain, there are t!o arameters listed, not three. The first thing that a ears to be a arameter is actually a class restriction. 1merge5ort1, as you !ould e6 ect, takes a list of ob"ects of some ty e (ty e 1a1), and returns a list of ob"ects of the same ty e. 5o !hy is the follo!ing ty e not sufficient<#
er6e5ort>a0?#pe :: &a' -> &a'

The reason this is insufficient is that at some oint in merge5ort the items in the list !ill need to be com ared to each other. This !ill be done using a com arison o erator such as 1U1, 1V1, 1UO1, or 1VO1. -n Haskell, those o erators are art of a class definition. The values for !hich 1U1 and so on are defined are those !hich are members of class 12rd1, so named because an 1order1 can be determined for them. 9any numeric ty es are of ty e 2rd, as are characters (ty e 1Char1) and strings (ty e 15tring1). merge5ort needs to com are the items in its in uts, so merge5ort must clarify its ty e. -ts arameter must be a list of ob"ects for !hich 1V1 and so on are defined. -t !ould also be okay to make the ty e more s ecific, but this is unnecessary and generally a bad techniIue. $nd !hat about 101< Ho! come four is of ty e 1a1, !here 1a1 is a member of class 1;um1< Can1t it "ust be a ;um< 2r an -nt< -t can be an -nt if !e s ecifically say it is, like so#
a = (4 :: Int) + *

Here 101 is an -nt. That is ho! you s ecify the ty e of something inside of an e6 ression. >ut !ithout that, 0 is of ty e 1a1, !here 1a1 is in class 1;um1, or more sim ly, 0 is of ty e 1a1 in class 1;um1. $nd that is im ortant, because 1D1 is defined for all member ty es of class ;um, meaning that 101 is definitely a legal arameter for this function#
0oubleIt :: :u a => a -> a 0oubleIt n = n + n

1-1 and 1Q1 are also defined for all member ty es of ;um, so 0 is also allo!ed for this function#
fib/ol# :: (:u a, :u b) => a -> b

fib/ol# n = fib(en/ol# 0 1 n fib(en/ol# :: (:u a, :u b) => b -> b -> a -> b fib(en/ol# a b n = $ase n of 0 -> a n -> fib(en/ol# b (a + b) (n - 1)

That is our first Haskell fib function, but !ith the ty es changed. The names have an added 1Poly1 so that an error doesn1t occur in the e6am le files because of a reused name. The ty e of 1fibPoly1 is read, GfibPoly is of ty e 1a1 to 1b1, !here 1a1 is a member of class ;um and 1b1 is a member of class ;um.G There is only one 1OU1 arro! because there is only ever one section of the ty e that describes class restrictions. The arentheses are reIuired. :hy !ould !e do this< 5houldn1t !e ick a single ty e for b rather than use a class< Here1s an e6am le. :hat if you !orked on a grou ro"ect, and t!o eo le need to calculate fibonacci numbers< $nd for reasons of their o!n, one needed an -nt returned and the other needed an -nteger< 2r a .ouble< :ould you !rite the code t!ice !ith different ty es< -f you !ere using C you !ould. @ou1d have to. Ksing general ty e classes allo!s code reuse in a !ay that is im ossible in other languages. $lso notice that in the initial call to 1fib4enPoly1, the third arameter is 1n1, the first arameter of 1fibPoly1, and that the ty es of 1fibPoly1 and 1fib4enPoly1 seem to make note of this. The reason - !rote 1fibPoly1 !ith a different return ty e from its arameter is that the follo!ing !ould be common#
fib :: Int -> Inte6er

:e only need -nt-si?ed storage of our counter in ut, but !e may need -nteger-si?ed storage of the result. Ksing t!o se arate ty es allo!s this. $lso, carefully check ho! ty es flo! in 1fib4enPoly1. The math does not mi6 arameters of ty e 1a1 and 1b1, and a arameter of ty e 1b1 is also used as the final return value. The ty es match not only e6ternally but internally. 7ollo!ing ty es through code in this manner !ill be im ortant for debugging. Continuing on!ard, in the fib e6am le !e used 1tail1. Here is its ty e#
tail :: &a' -> &a'

-n C, tail !ould have to be reim lemented for every ty e of list you used. That sounds like a slightly contrived roblem, so !hat about 1HH1, the inde6 o erator< -n most other languages, inde6ing a list is a built-in o erator, because it has to !ork for every kind of array. 5o it1s not actually a function. $nd so on. Everything in C is either overloaded, built in, or !orks for only one ty e. There are a fe! e6ce tions, generally involving casting to or from 1(void Q)1, but those are far outside the sco e of this tutorial. The oint is, you1re going to see 1;um a OU1 at the beginning of ty e signatures, as !ell as 1a1 and 1b1 inside ty e signatures. Here, 1a1 and 1b1 are ty e variables, used by the com iler solely to determine ro er ty es for com ilation. 2ccasionally you !ill get messages such as 1can1t determine ty e1, or 1ty e mismatch1. The second means the you1ve done something !rong, but the first usually means that a ty e variable can1t be inned do!n to a single ty e for a function that you1ve !ritten. This can ha en for the sim lest of reasons#
ain = put5tr@n (sAoB 4)

Previous versions of 4HC !ould not acce t this. Here1s !hy# 1 ut5tr/n1 takes a string and uts it on the screen. 0 has a 1 olymor hic1 ty e, i.e. it is a member of a ty e class, not defined as a s ecific ty e. 1sho!1 takes anything that can be turned into a string (basically), and so it doesn1t s ecify a ty e for 101 either. This leaves the com iler in a Iuandry, because no s ecific ty e is indicated any!here, and it !ill com lain. To resolve it, add the ty e definition like so#
ain = put5tr@n (sAoB (4 :: Int))

2r -nteger, or .ouble, or !hatever. This !ill be handy !hen you try to test generali?ed functions, and you1ll need it in a fe! other !eird cases as !ell. 2ne last note. @ou can define the ty e of multi le functions simultaneously# add2ne, subtract2ne ## -nt -U -nt This can be handy.

3. Part I30 *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 ty es match. 7or instance, let1s take a look at the e6tremely useful 1ma 1 function#
ap :: (a -> b) -> &a' -> &b'

>y no! you can robably read that, strange as it may be. Gma is of ty e function a to b follo!ed by a list of ty e a and returns a list of ty e bG. -t1s taking a function as a arameter. ;ot only that, but a olymor hic function, !ith no ty e restrictions. $nd look at the other t!o items. The function it takes is from a to b, and then it takes a list of ty e a and returns a list of ty e b. :ith a name like 1ma 1, it1s retty clear !hat should ha en !hen you use it#
foo@ist :: &Int' foo@ist = &2, 1, 5, 4' bar :: Int -> Int bar n = n - * *7ain> ap bar foo@ist &1,-1,2,*' *7ain>

;othing to it. -n the ast a ty e for at least 1foo/ist1 or 1bar1 !ould have been reIuired or Hugs and 4HC !ould have com lained that the ty es could not be fully determined. 1ma 1 is in the Prelude, and its descri tion can be found here# The Prelude, section# /ist 2 erations The e6am le using 1ma 1 sho!s that you can !rite functions !hich take functions as arameters. This can be fun and very useful. ;o! let1s try something stranger#
subCa$A.ro ?en :: &Int' -> &Int' subCa$A.ro ?en = ap (10 -)

:hat the heck< 7irst, for this to !ork there do need to be arentheses around the 1-1 and the 1'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 its ty e#
*7ain> :t (10 -) (10 -) :: (:u t) => t -> t *7ain>

5econd, 1ma 1 takes a function as its first arameter. There1s a reason that Haskell uses arro!s to define ty es, rather than a arenthesi?ed list. 1ma 1, a lied to 1('0 -)1 has the follo!ing ty e (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 ty e of ;um members, mind you) and returns a list of the same ty e (again, the same ty e member of ;um). This is constrained to +-nt, -U +-nt, by subEach7romTen1s ty e signature. $ lying the 1ma 1 function to less than its full list of arguments like this is called 1 artial 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 even name this 1in-bet!een1 state, since it is "ust a function like anything else. Here is 1subEach7romTen1 in action#
*7ain> subCa$A.ro ?en &4, +, ,, 11' &+,4,2,-1' *7ain>

-t does !hat you think it should, given ho! - named it. 3emember that a lying subEach7romTen to a list, even a named list, does not change that list, but merely returns the result. Take some time no! to lay around !ith artial evaluation, in addition to the list functions mentioned before and list com rehensions. 3emember that functions grab their arameters 1eagerly1, so you have to ut arentheses around any arameters that are com osed of a function !ith its o!n arameters.

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


.1 Part I0 Did 9ou Take T!at 4reak1 Here Are Patterns
Ho efully you are no! comfortable defining and using functions in Haskell using your choice of Hugs, 4HC, or 4HCi. ;o! it1s time to talk about all the !ays in !hich functions can 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 ty e. Even functions !ith no arameters each have a ty e, i.e. global and local variables. -t is not al!ays necessary to !rite this ty e, as Haskell com ilers can

determine it. Ho!ever, !riting it is a good ractice and sometimes a necessity. :e are about to cover a lot of synta6, so after reading this section, it !ould be a good idea to read the Tour of the Haskell 5ynta6 listed in the introduction. There are a fe! e6am les !e can go through to make that age clearer. 7irst, a sim le function that !alks do!n a list and sums its members#
su "ll :: :u a => &a' -> a su "ll (-:-s) = - + su "ll -s su "ll &' = 0

This is a recursive function. -t takes a list of 1a1 in ;um and returns an 1a1. Ho!ever, there seem to be t!o definitions for sum$ll. $nd there are. This is ho! attern matching !orks. The t!o definitions have different s ecifications for their arameters, and each time sum$ll is called, !hichever attern matches the arameters !ill be evaluated. /et1s look at each definition. The second definition is the clearest. 1+,1 is the em ty list, and sum$ll of an em ty list is defined here as ?ero. The middle line has something odd about it, though. 1(6#6s)1 is listed 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 a art its in ut. There are a fe! atterns !hich do this, and this 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 the front. -n other !ords, it !ill match lists !ith at least one member. The choice of variable names 161 and 16s1 is com letely arbitrary, but since 161 !ill be 1bound1 to the first member of the list and 16s1 !ill be 1bound1 to the remainder of the list, it is some!hat natural to !rite one 161, and then the remaining 16s1 !hen describing the list. :hen the attern 1sum$ll (6#6s)1 matches the in ut, 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 of adding said first value to the result of calling sum$ll on the rest of the list. Patterns are checked to -to-bottom, so !hen 1sum$ll (6#6s)1 fails to match, 1sum$ll +,1 is checked. 5ince the only attern that could fail to match 1sum$ll (6#6s)1 is an em ty list, 1sum$ll +,1 !ill definitely 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 com licated 1s!itch1 statements or 1if1 blocks in favor of sim ly !riting se arate definitions for distinct in uts. This allo!s code to be clear and concise. Patterns can also be more s ecific. The fib e6am le can be re!ritten as follo!s#
fib/at :: (:u a, :u b) => a -> b fib/at n = fib(en/at 0 1 n fib(en/at :: (:u a, :u b) => b -> b -> a -> b fib(en/at a D 0 = a fib(en/at a b n = fib(en/at b (a + b) (n - 1)

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

.2 Part II0 After Patterns2 &uards


5ometimes functions need more com licated !ork to choose bet!een definitions. This can be done !ith guards, sho!n here#
sAoB?i e :: Int -> Int -> 5trin6 sAoB?i e Aours inutes ) Aours == 0 = 41*4 ++ 4:4 ++ sAoB7in ++ 4 a 4 ) Aours != 11 = (sAoB Aours) ++ 4:4 ++ sAoB7in ++ 4 a 4 ) Aours == 1* = (sAoB Aours) ++ 4:4 ++ sAoB7in ++ 4 p 4 ) otAerBise = (sAoB (Aours - 1*)) ++ 4:4 ++ sAoB7in ++ 4 p 4 BAere sAoB7in ) inutes ! 10 = 404 ++ 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 e6 ression, and they are checked in order. The first !hich is found to evaluate to True !ill have its corres onding e6 ression evaluated and returned. The function !ill be eIual to that e6 ression for the case that that guard is true. 1other!ise1 is eIual to True, and !ill therefore al!ays be acce ted if it is reached. 1other!ise1 is a convenience, not a necessity. 1DD1 is the list concatenation o erator. -t is used here for the follo!ing reason#
5trin6 :: &EAar'

5o all of that makes sense e6ce t for the 1!here1 stuff. Here - thre! in something e6tra, and used 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, so instead of an 1if1 statement or 1case1 statement, - used guards again to describe its t!o definitions. -n all, this function takes an hour (ho efully from 0 to %3) and minutes (ho efully 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 im ortant to note that the variables defined in 1!here1 clauses and their cousins, 1let1 clauses, are only in sco e for the attern in !hich they e6ist. 5o a function defined !ith multi le 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 1ifthen1 doesn1t !ork. That said, here1s a sim le e6am le#
sAoB7s6 :: Int -> 5trin6 sAoB7s6 n = if n ! ,0 tAen 4failin64 else 4passin64

;ot much to it. 5ince 1sho!9sg1 has a return ty e of 5tring, the values in both the 1then1 clause and the 1else1 clause have to also be of that ty e. 1if1 does not need to be the entire definition of a function. 7or instance#
sAoB@en :: &a' -> 5trin6 sAoB@en lst = (sAoB (tAe@en)) ++ (if tAe@en == 1 tAen 4 ite 4 else 4 ite s4) BAere tAe@en = len6tA lst

. Part I30 Indention '(nta)


@ou may have noticed that - use indention to indicate lines that are art of a block of source code. This is not sim ly good style, but it is also art of Haskell1s synta6. -ndentation denotes structure. 5 ecifically, 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!o functions one line after another. -nstead it demands a blank line to indicate that the definition of a function has truly finished. This all enforces good style, and it greatly reduces the amount of "unk synta6 in the language, such as 1W1, 1X1, and 1P1.

.+ Part 30 And Lambda *unctions


4iven a rogrammer1s ability to define functions locally in Haskell, you might ask, G-s there an even more brief !ay of defining functions<G Knlike this tutorial, Haskell does let you finish Iuickly#
(F- # -> - * 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 little like the greek letter lambda, !hich ha ens 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 com utation theory, etc. @ou can find out more about it other laces. The oint is that !hen you !rite 1(Y1, you have started a 1lambda e6 ression1, !hich generally look a lot like the one above. -t has 1(Y1, then some variable names (usually short ones), a 1-U1 arro!, and an e6 ression !hich uses those variables. $nd of course 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 e6am le#
/relu0e> ap (F- -> 4tAe 4 ++ sAoB -) &1, *, 2, 4, 5' &4tAe 14,4tAe *4,4tAe 24,4tAe 44,4tAe 54' /relu0e>

- mention lambda functions because they come in handy, but also because they are used often in the more com licated e6am les. 2f course, lambda functions cannot be recursive, since

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 3I0 Pol(mor#!ic T(#es and T(#e Constructors


The sim lest Haskell rogram is the follo!ing#
ain = return ()

The variable 1main1 is a reserved !ord, and !hatever its value is, the rogram e6ecutes. Here is the obligatory GHello :orldG rogram#
ain = put5tr@n 4Gello Horl04

$nd the ty e of 1main1#


ain :: I= ()

This is another !ay of saying Gmain is of ty e something or otherG. :ell, that1s ho! it looks any!ay. :hat !e have here are e6am les of t!o strange things at once. That ha ens a lot !hen you1re learning Haskell, and that1s !hy -1m !riting such a long tutorial in the first lace. 1()1 is a ty e. The only value of ty e 1()1 is !ritten 1()1. $nother !ord for this ty e and its singular value is 1null1. 5o this ty e can be read Gmain is of ty e -2 nullG. >ut !hy is it read that !ay< :hat does it mean to ut one ty e after another< -2 is not a ty e. The !ord 1-21 is only art of a ty e. 1-2 a1 is a ty e. 1-21 is a ty e constructor !hich takes a ty e as a arameter. .ee breath. This is not the same thing as a class. :hen !e !ere talking about classes, - said that functions !ere olymor hic, meaning that they could o erate on values of any ty e rovided that the ro er functions !ere defined for it. @ou can create a ty e 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 you do that correctly, any function !hich has 1;um a OU1 at the beginning of its ty e !ill acce t your ne! ty e and everything !ill !ork fine. >ut 1-21 isn1t a class, or a olymor hic function. This is something stranger. -t is a olymor hic ty e. .id that make sense< $ ty e that takes another ty e as a arameter< /et1s look at an e6am le from the standard libraries#
0ata 7a#be a = :otAin6 ) Iust a

This ty e can be found here# htt #FF!!!.haskell.orgFghcFdocsFlatestFhtmlFlibrariesFbaseF.ata-9aybe.html This is a 1data1 ty e definition. The values on the right are se arated by 1T1, the i e symbol, !hich can be read here as GorG. This ty e says, Ga value of ty e 19aybe a1 can be 1;othing1, or can be 1Eust a1G, that is 1Eust1 follo!ed by a value of ty e 1a1. Here1s an e6am le using 9aybe in attern matching#

sAoB/et sAoB/et sAoB/et na e ++

:: 7a#be (5trin6, Int, 5trin6) -> 5trin6 :otAin6 = 4none4 (Iust (na e, a6e, spe$ies)) = 4a 4 ++ spe$ies ++ 4 na e0 4 ++ 4, a6e0 4 ++ (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 ty es listed after 1;othing1 and before the 1T1 in the ty e definition for 19aybe a1. The second matches a value of 1Eust1, the second 1data constructor1 for 9aybe. 1Eust1 does have a tu le after it, "ust like in the ty e definition, and arentheses are used to grou these t!o things in the attern. The !ords 1Eust1 and 1;othing1 are arbitrarily chosen, although good choices. -t is im ortant that the first letter is ca itali?ed. $s you may have noticed, throughout Haskell, variables have lo!ercase first letters and ty es have u ercase first letters. This is a art of Haskell1s synta6. .ata constructors are not variables, and so the convention is e6tended to reIuire their first letters to also be ca itali?ed.

.: Part 3II0 T!e I$ -onad


5o let1s get back to 1main1 and its ty e, 1-2 ()1. -2 is a olymor hic ty e. >ut !hat is it< Knfortunately, - cannot sho! you its definition. 1-2 a1 is a art of the Haskell standard, and most of its im lementation is 1under the hood1. -ts im lementation is also very large, and involves a lot of lo!-level code. 1-21 is a member of the class 9onad, !hich means (very briefly) that it lets you !rite seIuential-looking code using the 1do1 notation !hich -1ll sho! in minute. 1-21 is also short for -n utF2ut ut of course, and that means that the 1under the hood1 functions of -2 let you read and !rite the !orld state. 5o 1-21 is ho! Haskell interacts !ith the real !orld. $gain#
ain :: I= ()

9onads are odd things, and a function of ty e 1-2 a1 !ill erform an 1-21 o eration and return a value of ty e 1a1. -n this case, main !ill return a value of ty e 1()1, namely 1()1, or 1null1. 5o main is al!ays Gan -2 o eration that returns nullG. Here is short main function, !ith ty es. ;ote that it is never necessary to s ecify the ty e of main.
so e.un$ :: Int -> Int -> &Int' so e.un$ ;;;;;;;;; ain = 0o put5tr 4pro pt 14 a !- 6et@ine put5tr 4pro pt *4 b !- 6et@ine put5tr@n (sAoB (so e.un$ (rea0 a) (rea0 b)))

Here1s !hat1s going on# The -2 9onad binds blah blah blah that1s all in the other tutorials and yet 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 it doesn1t al!ays return the same value. @ou can1t say that the function 1get/ine1 is GeIualG to

anything, since its value may be different every time it is referenced. This is in contrast to a value, like 101, !hich !ill al!ays be the number 0. 5o -2 is hard to do if you !ant a language that has true GeIualityG !hen you !rite an assignment. T!is !as actuall( been t!e biggest stumbling 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 Haskell does something !eirder. There1s an obscure branch of mathematics, namely monads, that concerns state transformation functions. The authors of Haskell used it to let you !rite mathematical functions that denote changes in the !orld1s state !ithout breaking that nice eIuality stuff. +Ho!1s that for sim le< 5ee ho! - made it all make sense by a ealing to a higher authority< Haskell !orks by magicH -Eric, >riefly, the -2 monad takes the state of the !orld, alters it !ith some function, and asses it for!ard to be the in ut for another -2 function. -n the e6am le, the functions 1 ut5tr1, 1get/ine1, and 1 ut5tr/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 e6 ect. Thus the main function of the rogram above !ill ut a rom t on a screen and read in a string, and then do it again, then rint something. The 1(read 6)1 function takes a string and returns a number of !hatever ty e 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 dis lay it. !ill return to this code and make it useful later. The descri tion of -2 may sound like 1im erative1 behavior, and it is, !ith a t!ist. -n ut and out ut need to ha en in a certain seIuence in a rogram, but a mathematical function1s arts can be determined in any order as long as it eventually finishes. 5eIuence doesn1t matter for the evaluation of a mathematical definition, and most Haskell code is !ritten in that manner. 5o !hat about in ut and out ut< Can they be mathematically described< $s it turns out, they can. 9onad theory means that a function can be GeIualG to the act of transforming a state. The mathematical frame!ork for monads ca tures the idea of seIuenced actions, and that let Haskell1s creators give 1-2 a1 a ty e that could be used "ust like any other ty e. :hen a seIuence of monad functions are evaluated, for instance !hen 1main1 is evaluated, the monad functions are a lied in seIuence to the initial state. >efore that evaluation, Haskell gets to treat functions of ty e 1-2 a1 "ust like anything else, i.e. as e6 ressions !aiting to be evaluated. That means that the 1-2 a1 ty e doesn1t have to be a s ecial, builtin art of Haskell, even though in ut and out ut have to be art of the standard libraries and im lemented !ith system calls. -t does mean that doing -2 in Haskell means using a olymor hic ty e 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 unless other!ise noted, they are la?y. This means that the only thing that forces evaluation is binding an 1-2 monad1 function to 1main1. /ot!ing is e7er e7aluated unless it is going to be t!e return 7alue of an e7aluated "monad" function2 or unless it is needed to com#ute suc! a return 7alue. That the 1-2 monad1 forces evaluation isn1t really im ortant, but it !ill e6 lain 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 im erative-style rograms in Haskell. That is a direct result of the behavior of the -2 monad. .oing so !ould be

ina ro riate, because Haskell has much more o!er than that. - say that because - have not seen any other tutorial do so, and - think it is im ortant. -f you !rite rograms that call outside libraries, you1ll deal !ith the -2 monad a lot. Everything that deals !ith the rest of the com uter is art of the -2 monad, such as driver calls, net!ork libraries, file access, threading, and system calls. There are other monads in Haskell1s 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, after understanding 1foldr1 and variants. -t1s retty hard, but not because it1s com licated. :riting your 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 e6am le that demonstrates ho! to !rite a monad from scratch, but it may not be necessary for a general Haskell rogrammer to learn that.

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


/et1s return to basic -2 monad usage. Here1s the e6am le main rogram again#
so e.un$ :: Int -> Int -> &Int' so e.un$ ;;;;;;;;; ain = 0o put5tr 4pro pt 14 a !- 6et@ine put5tr 4pro pt *4 b !- 6et@ine put5tr@n (sAoB (so e.un$ (rea0 a) (rea0 b)))

T!is is a general framework for learning Haskell. $side from altering the number of arameters to 1some7unc1 ( erha s ?ero), this is all you !ill really need for a main function until you feel comfortable !ith Haskell. -t is good enough for most sim le tasks, and you can use it to test out ideas in 4HC by re lacing the definition of 1some7unc1 !ith !hatever function you1re trying to !rite. @ou !on1t need it for !orking in Hugs or 4HCi, but you !ill if you com ile !ith 4HC. -n Hugs and 4HCi, you only need to make a source code file that includes some7unc1s definition. :hat - said earlier about the indentation techniIue removing e6traneous synta6 isn1t Iuite true. 1W1, 1X1, and 1P1 do e6ist in Haskell. They are an alternative to the the !hites ace-defining notation used here, and are sometimes but rarely referable. The !hites ace method is very sim le, and the e6am le sho!s most of its synta6. >locks begin on tabbed or s aced lines and further indention is used for se arate blocks. Ksing 1do1 signals to the com iler to e6 ect indentation based on !hites ace unless you then use 1W1, 1X1, and 1P1. The 1(read 6)1 items use the 1read1 function found here# The Prelude# the 1read1 function

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 ty es, such as 1-nt1, 1+-nt,1, 15tring1, or even 1(5tring, +-nt,)1. The ty e 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 and 1Q1 are class methods defined for members of 1;um1. @ou can see those here# The Prelude, section# the ;um class The ty es of the -2 functions, s ecifically 1 ut5tr1, 1get/ine1, and 1 ut5tr/n1, are given here# 5ystem.-2, section# 5 ecial cases for standard in ut and out ut and also here, in the Prelude, !hich is !hy they are in sco e normally# The Prelude, section# 5im le -F2 o erations $s you can see from the documentation, !hen ut5tr/n is a lied to a 5tring, you get a value of ty e 1-2 ()1. The 1null1 means that no useful information is returned by the function. -t altered 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 o eration to a variable. 1get/ine1 has a ty e of 1-2 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 sco e at that oint in the function and !hen the monad function is evaluated, and its return value !ill be assigned to the variable. -f a function is not refaced by a left arro! and a variable, then its return value is ignored, although !hatever that function did to the state carried by the monad still ha ens. 7or instance, if you do not bind the return value of 1get/ine1 to a variable, you don1t store the line the user ty ed in, but it is still read in and buffers are messed !ith, etc., meaning that another get/ine !on1t return it. There is one e6ce tion to this 1ignoring1 of return values not bound to variables. -t is no accident that the last line in the seIuence has the same return ty e as main. :hen using monads to com ose seIuences of o erations, the last line in a function must have the same -2 ty e as the function itself. :hen this is not natural, use 1return1 !ith an a ro riate value#
6et:a e1 :: I= 5trin6 6et:a e1 = 0o put5tr 4/lease enter #our na e: 4 na e !- 6et@ine put5tr@n 4?Aan8 #ou; /lease Bait;4 return na e

1 ut5tr/n1 has a ty e 5tring -U -2 (), but -2 () doesn1t match the ty e of 1get;ame1, !hich is -2 5tring. 1return name1 is used to end the function !ith a function of the ro er ty e, and to return the data !e !anted to return. :ithout the re ly message, this function can be !ritten much more succintly#

6et:a e* :: I= 5trin6 6et:a e* = 0o put5tr 4/lease enter #our na e: 4 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 im erative, 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 this necessary< -s it a good idea to have im erative-looking code calling la?y, functional code< -n my o inion, it can be. @ou get to s ecify the order of e6ecution for those o erations that reIuire it (such as -2), and you get o!erful functional tools the rest of the time. @ou also get a hurt head. 5o take a break. - need one from !riting all of this. The ne6t section !ill be on advanced ty e declarations.

+ 'ection I30 Haskell and 9ou


+.1 Part I0 .!ere Are t!e "*or" Loo#s1
$s you may have noticed, the aren1t any 1for1 loo s in Haskell. @ou could !rite them using -2 monad functions, but - said that !asn1t the right thing to do. 5o !here are they< -f you1ve already figured Haskell out, you can ski this section, but for those you like me that needed a lot of assistance, read on. 1for1 loo s are unnecessary. ;ot "ust in Haskell, but in general. The only reason that you have ever used 1for1 loo s is that you had to 1do1 something to a chunk of memory to store the right value in the right s ot. Haskell frees you from this, and !hen you got lost and !onder !here your 1for1 loo s are, check here#
bar :: Int -> Int bar = ;;; foo :: &Int' -> &Int' foo (-:-s) = bar - : foo -s foo &' = &'

That looks a little too easy, and is actually eIuivalent to 1foo O ma bar1. Here1s a less contrived e6am le. :hat if you !ere im lementing a hysics simulation, gravity for e6am le, and you needed to calculate a ne! osition of each ob"ect based on the other ob"ects1 ositions< The follo!ing function calculates art of the rocess, !hich is finding, for each ob"ect, the sum of its mass times another ob"ect1s mass divided by distance, over all other ob"ects. -n C, this !ould be accom lished by a air of nested for loo s, the outer one reading the mass and osition from an array of ob"ects, and the inner one com uting mass' times mass% over the distance and summing it. Here are the ty es for that o eration in Haskell#
--t#pes for Jariables t#pe 7ass = Kouble $larif#in6 para eters --onl# a t#pe rena e, but useful for

t#pe /os = (Kouble, Kouble, Kouble) t#pe =bL = (7ass, /os) (Kouble, Kouble, Kouble))

---, #, % --inter$Aan6eable BitA (Kouble,

--list of fun$tions nee0e0 {?a8es a list of obLe$ts; Meturns a list of (su of ass ti es otAer obLe$t all obLe$ts) =r0er is preserJe0; -} --oJerall fun$tion t#pe $al$7asses=JerKists :: &=bL' -> &Kouble'

ass oJer 0istan$e for

That1s definitely the setu . - defined some ty es for kee ing track of the variables, listed the mathematical o erations needed, and defined a ty e 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 o en and close block comments. The reason that - se arate this from the code is that it is unlikely to change, !hile code is likely to be altered, o timi?ed, debugged, etc. :ith some useful comments, here1s one !ay to !rite the code#
--Gere Be pass tAe obLe$ts in as tBo para eters to tAe Aelper fun$tion so Be $an iterate tBi$e; --?Ais 0oes not $op# tAe list of obLe$ts; $al$7asses=JerKists :: &=bL' -> &Kouble' $al$7asses=JerKists obLs = $al$Gelper obLs obLs --?Ais is a fun$tion tAat $o putes a 0istan$e betBeen tBo /os Jalues, use0 in $al$77oK; 0istNOP :: /os -> /os -> Kouble 0istNOP (-1, #1, %1) (-*, #*, %*) = sQrt (-0 * -0 + #0 * #0 + %0 * %0) BAere (-0, #0, %0) = (-1 - -*, #1 - #*, %1 - %*) --tAree assi6n ents at on$e usin6 a tuple --?Ais iterates oJer tAe list of obLe$ts an0 $al$ulates tAe su for ea$A; --It uses pattern at$Ain6 to re$urse an0 ter inate; $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 ti es ass oJer 0istan$e for a sin6le obLe$t; --It uses pattern at$Ain6 to re$urse an0 ter inate an0 a BAere $lause to 8eep tAe $o0e $lear; $al$77oK :: =bL -> &=bL' -> &Kouble' $al$77oK obLR( 1, pos1) (( *, pos*):rest) = safeSalue : $al$77oK obL rest BAere 0ist = 0istNOP pos1 pos* safeSalue = if pos1 == pos* tAen 0 else 1 * * < 0ist $al$77oK D &' = &'

- thre! something e6tra in there, s ecifically 1ob"Z1 in front of 1(m', os')1. The 1Z1 is read 1as1, and it means that 1ob"1 !ill refer to the !hole value of ty e 12b"1, !hile 1(m', os')1 !ill attern match against the values in 1ob"1. -t1s handy, because other!ise - !ould have to !rite 1(m', os')1 again !hen - called 1calc99o.1 recursively, and - might make a ty o !hen did. $lso, it1s clearer. ;ote also that - did not have to com letely 1take a art1 ob". - left the value of ty e 1Pos1 bound to 1 os'1. $nd note that - ut all the sub-com utations for 1distC@R1 into one line to save s ace. - defined the tu le 1(6' - 6%, y' - y%, ?' - ?%)1, and then bound it to the attern of 1(6d, yd, ?d)1, thus defining 16d1, 1yd1, and 1?d1 ho! - needed to. 7inally note that dist 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 com are eIuality bet!een os' and os% because a tu le of ty es !hich are all in the class 1EI1 is also in the class 1EI1. The definitions allo!ing that are here, although you have to scroll 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 1-nstances1 section of the EI class, that means that some!here in the source code for the Prelude, there is an instance of EI defined for 1(a, b)1 !ith the condition that both a and b are also members of EI. The definition of that instance is fairly straightfor!ardP the oint is that it is there. >ecause it is resent, any tu les of si?e % (and also those of many larger si?es) !hose items are all members of the EI class, and those tu les can be com ared using 1OO1 and 1FO1 !ithout any further !ork on your art. 1sIrt1 is a class function, and is defined (se arately) for all ty es in the class 17loating1, !hich of course includes 1.ouble1. The ty e of 1sIrt1 can be found here# The Prelude, section# the 7loating class 1sum1 is a olymor hic function, and is defined (one time) for all ty es in the class 1;um1, !hich also of course includes 1.ouble1. The ty e of 1sum1 can be found here# The Prelude, section# 5 ecial 7olds - could have had calc99o. return the sum, but code !ill com ile to a more efficient result if the tasks are broken u , since 1sum1 in the Prelude is based on a tail-recursive and (believe) highly o timi?ed function. The definition of 1sum1 is in the Prelude, and more about 1tail recursion1 can ho efully be found here# htt #FFen.!iki edia.orgF!ikiFTailNrecursion 5o !here are the 1for1 loo s< Each recursive function iterates over a list, and the t!o together act as a nested air of 1for1 loo s. This code is good, but there is a Iuicker !ay to !rite 1calc9asses2ver.ists1 and 1calc99o.1, !ith the same ty es, and using a much sim ler hel er function for 1calc99od1. Here is a cleaner im lementation#

--Gere Be use T apT instea0 of Britin6 tAe re$ursion out; $al$7asses=JerKists :: &=bL' -> &Kouble' $al$7asses=JerKists obL@ist = ap (FobL -> su ($al$77oK obL obL@ist)) obL@ist --"6ain, Be use T apT instea0 of Britin6 tAe re$ursion out; $al$77oK :: =bL -> &=bL' -> &Kouble' $al$77oK obL obL@ist = ap ( 7oKGelper obL) obL@ist --Gere Be 0onTt botAer spa$in6 out tAe $o0e sin$e BeTre not for in6 a list an# ore; --:ote tAat tAis fun$tion no lon6er operates or returns a list; 7oKGelper :: =bL -> =bL -> Kouble 7oKGelper ( 1, pos1) ( *, pos*) = if pos1 == pos* tAen 0 else 1 * * < 0istNOP pos1 pos* --?Ais is un$Aan6e0; 0istNOP :: /os -> /os -> Kouble 0istNOP (-1, #1, %1) (-*, #*, %*) = sQrt (-0 * -0 + #0 * #0 + %0 * %0) BAere (-0, #0, %0) = (-1 - -*, #1 - #*, %1 - %*)

- could have also avoided !riting 1m9o.Hel er1 by using a lambda function#
--5a e as aboJe; $al$7asses=JerKists :: &=bL' -> &Kouble' $al$7asses=JerKists obL@ist = ap (FobL -> su obL@ist

($al$77oK obL obL@ist))

--?Ae $o0e BAi$A aJoi0s 0iJision b# %ero is noB in$lu0e0 Aere; $al$77oK :: =bL -> &=bL' -> &Kouble' $al$77oK ( 1, pos1) obL@ist = ap (F( *, pos*) -> if pos1 == pos* tAen 0 else 1 * * < 0istNOP pos1 pos*) obL@ist --?Ais is un$Aan6e0; 0istNOP :: /os -> /os -> Kouble 0istNOP (-1, #1, %1) (-*, #*, %*) = sQrt (-0 * -0 + #0 * #0 + %0 * %0) BAere (-0, #0, %0) = (-1 - -*, #1 - #*, %1 - %*)

2r - could have avoided !riting calc99o., but at that oint it gets ridiculous#
--:oB Be AaJe neste0 la b0a fun$tions BAi$A aJoi0 a fun$tion $all; --:ot reall# ne$essar#, sin$e no $larit# is 6aine0; $al$7asses=JerKists :: &=bL' -> &Kouble' $al$7asses=JerKists obL@ist = ap (FobL1R( 1, pos1) -> su ( ap (F( *, pos*) -> if pos1 == pos* tAen 0 else 1 * * < 0istNOP pos1 pos*) obL@ist) ) obL@ist --?Ais is un$Aan6e0; 0istNOP :: /os -> /os -> Kouble 0istNOP (-1, #1, %1) (-*, #*, %*) = sQrt (-0 * -0 + #0 * #0 + %0 * %0) BAere (-0, #0, %0) = (-1 - -*, #1 - #*, %1 - %*)

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

note that none of these take much code to !rite. Haskell is like that. m9o.Hel er is artially a lied in this e6am le. -t is given only one of its t!o arameters !here it is !ritten in calc99o.. The ty e of 1m9o.Hel er ob"1 in that e6 ression is#
7oKGelper obL :: =bL -> Kouble

This in turn is suitable as a arameter to 1ma 1, as it only takes one arameter, rather than t!o. ;ot every instance of a for loo should be turned into a 1ma 1. -n this case, there is the Prelude function 1sum1, !hich !ill take the list generated by the 1ma 1 in calc99o. and return the sum of its values. There is not al!ays a re-built function for your ur oses. /ist functions are art of Haskell1s core tools, and there are more advanced functions to use !hen you need them, such as 1foldr1 and its variants. /earning ho! to use 1foldr1 and 1foldl1 is a rite of assage for Haskell rogrammers. @ou !ill learn 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 loo s !ere "ust the beginning. :hen you get a!ay from seIuential behavior, real o!er comes out. $lso, kee in mind that since foldr and ma are used every!here, 4HC has heavily o timi?ed them, and functions like them, so it1s a good idea to use them.

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


This section fleshes out the fle6ibility of the Haskell ty e system in a !ay that - haven1t seen described for ne!comers before. Ho efully, your are at least familiar !ith the conce t of a 1Tree1, that is, a data structure !hich has nodes that contain values and may also oint to further nodes in the structure. 1>inary Trees1 are one of the common forms, i.e. trees !here each node has at most t!o children. 7or those of you for !hom this is ne!, note this isn1t a general gra h. Trees aren1t su osed to loo back on themselvesP they "ust branch.
0ata ?ree a = :ull ) :o0e a (?ree a) (?ree a)

This is a relatively com licated ty e. -t is a 1data1 ty e, defined !ith the reserved !ord 1data1, like 19aybe a1 !as. -t is also olymor hic like 19aybe a1P you can tell because the ty e, 1Tree a1, takes a ty e 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 on ins ection it is a binary tree, having t!o children in 1;ode1. 5o ho! !ould this !ork< 7irst, let1s !rite a value of this ty e#
t1 :: ?ree Int t1 = :o0e 2 (:o0e * :ull :ull) (:o0e 5 (:o0e 4 :ull :ull) :ull)

-f !e !ere to gra h this tree, not including ;ull branches, it !ould look like this#
2 < F 4 <

The first node has both a 1left1 child and a 1right1 child, and the 1right1 child of the first node also has a 1left1 child. /et us revie! 1constructors1. -n this e6am le 1Tree a1 is a ty e, and 1;ode1 and 1;ull1 are 1data constructors1 for that ty e. $ data constructor, often sim ly called a constructor, acts like a function that grou s together ob"ects to form an ob"ect of a dataty e. They only e6ist for ty es defined using 1data1 or 1ne!ty e1. ;ote that they are different from ty e constructors, such as -2 and 9aybe. .ata constructors act like functions, and do not belong in ty e signatures. Ty e constructors act like functions on ty es, and onl( belong in ty e signatures. They do not live in the same names ace, so often a 1data1 ty e !ill have a data constructor of the same name out of convenience. Constructors are also used to 1deconstruct1 ob"ects of 1data1 ty es, like so#
in=r0er@ist :: ?ree a -> &a' in=r0er@ist :ull = &' in=r0er@ist (:o0e ite left ri6At) = in=r0er@ist left ++ &ite ' ++ in=r0er@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 values to the variables 1item1, 1left1, and 1right1, !hich are of ty es 1a1, 1Tree a1, and 1Tree a1, res ectively. :e kno! these ty es because ;ode1s definition reads, G;ode a (Tree a) (Tree a)G, and 1a1 is not further s ecified in this e6am le. 7or those of you unfamiliar !ith trees, 1t'1 above is a 1binary search tree1, and evaluating 1in2rder/ist t1 !ill result in the follo!ing#
*7ain> in=r0er@ist t1 &*,2,4,5' *7ain>

Those values are in ascending order, since that is the definition of a 1binary search tree1. 3ead u 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 to define each child. @ou can do that in Haskell as !ell as C, but as usual, there1s a t!ist, and again as usual it involves la?y evaluation. -n CFCDD, to use a ty e in its o!n definition, you must declare a ointer to an ob"ect of its ty e rather than including it directly. -n Haskell, ointers aren1t used like that, so the ty e is included directly, as in the tree e6am le. 5o !hat about this definition#
foo :: Int -> ?ree Int foo n = :o0e n (foo (n - 1)) (foo (n + 1)) t* = foo 0

:hat is the value of 1t%1< $nd !hat is its ty e< The value of 1t%1 reIuires an infinite amount of s ace to store. The first fe! levels of the trees could be dra!n like this#
0 -1 < F < F 1 < F

-* 0 0 * < F < F < F < F

$nd so on. >ut the ty e of 1t%1 is sim le, and should be clear from the ty e of 1foo1#
t* :: ?ree Int

:hen you get an error message (not if ever, but w!en you get an error message) that says Gcan1t do such-and-such, unification !ould result in infinite ty eG, it means that the ty e !ould reIuire an infinite amount of s ace to store. Ty ically this ha ens !ith attern matching 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 ty e that looks like this#
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&;;;;

$nd so on. >ut back to 1t%1. -ts ty e is not infinite, even though its ty e is defined recursively and t% has a value that, !hen evaluated, !ould reIuire infinite s ace to store. >ecause its ty e is defined recursively, Haskell (and you) kno! that values of ty e 1Tree a1 can contain other values of ty e 1Tree a1. The fact that each value of ty e Tree a !hich is 1in1 t% uses the constructor 1;ode1 is not stored in the ty e of t%, so the ty e of t% is finite and Haskell can use it. $lso, multi le values of ty e 1Tree -nt1 can e6ist, some infinite, some not, and they all have the same ty e. 2kay<

+.3 Part III0 T!e Point<s=


- !rote all this about ty es to drive t!o oints home. 7irst, Haskell uses la?y evaluation. 7or e6am le, the follo!ing ty e is valid and Haskell !ill not com lain about it#
0ata .oreJer a = "?Ain6 a (.oreJer a)

-t is a olymor hic ty e, it has a single constructor 1$Thing1, and it is recursive. =alues of this ty e !ill al!ays be infinite if fully evaluated. That1s okay, and you could use this in a rogram if you !anted to. Haskell !ould not attem t to fully evaluate an ob"ect of this ty e unless you told it to. The second oint is that learning and using Haskell reIuires unlearning and rethinking the basic assum tions most coders have develo ed about rogramming. Knlike so many languages, Haskell is not 1a little different1, and !ill not 1take a little time1. -t is very different and you cannot sim ly ick it u , although - ho e that this tutorial !ill hel . -f you lay around !ith Haskell, do not merely !rite toy rograms. 5im le roblems !ill not take advantage of Haskell1s o!er. -ts o!er shines most clearly !hen you use it to attack difficult tasks. 2nce Haskell1s synta6 is familiar to you, !rite rograms that you !ould ordinarily think of as too com licated. 7or instance, im lement gra h-s anning algorithms and balanced-tree data ty es. $t first, you1ll robably trudge ahead using 1im erative thought rocesses1. $s you !ork, you1ll ho efully see that Haskell1s tools let you dramatically sim lify your code. A big ti# is2 >Don"t use arra(s.> 9ost of the time, you need to access members of a list one at a time, in order. -f that is the case, you do not need an array, and it !ould take you a lot of

!ork to set one u . Kse a list. -f you are truly storing data that needs random access, still don1t use arrays. Kse lists and 1HH1. :hen you need s eed, then use arrays. Kse $rrays, and then s!itch to -2$rrays. >ut only use them if you actually need s eed. @our class ro"ects absolutely !ill not need arrays unless you are !riting a game, or !orking on something for at least three months. Then, you might need fast random-access data. 9aybe. Kse lists. The tutorial has been e6 anded to include section si6 after the commentary, !ith e6am les. $dditionally, all e6am les from these sections are included in source files as !ell. Ho efully, these !ill sho! ho! Haskell im lementations differ from im erative code. Check them out and com are them to your o!n Haskell rograms. 9y style is not erfect, but - kno! some good techniIues. $s a general rule, shorter, more concise source code makes rogramming and debugging faster. -f you find yourself !riting e6tensive cases or re eated code, that1s robably unnecessary in Haskell.

, 'ection 30 *inal Commentar(


,.1 Part I0 .!( is "%eferential Trans#arenc(" .ort! An(t!ing1
7unctional languages have often been accused of generating slo! code. This is not the case !ith Haskell, e6ce t for the $rray ty e. 5!itch to -2$rrays if you need s eed. $ny!ay. 3eferential trans arency gives Haskell rograms t!o big boosts# better e6ecution s eed and memory use, and shorter, clearer code. 7irst, here are some reasons !hy Haskell rovides better s eed and memory use. ;o code runs faster than code evaluated during com ilation, e6ce t code o timi?ed a!ay during com ilation. The easiest !ay to evaluate during com ilation is to find !here a value is assigned to a variable, find !here that variable is ne6t read, and hardcode the value in that lace. This avoids a memory !rite, ossibly a read, and also otentially some memory allocation. -n both C and Haskell (for e6am le), functions inherit the names ace of their sco e. -n C, this means that any variable in sco e can be accessed at any time. 7or rogramming, this can be a good thing, or at least a time-saving feature. Ho!ever, for com iling, this is a >ad Thing. $ny of those accesses could be a !rite. :orse, you could have assigned a ointer the value of the memory s ace of a local variable, or be running a multi-threaded a lication. 2r you could do ointer arithmetic and mess !ith any memory location at all. The behavior for handling this in C is com iler s ecific. C rogrammers are su osed to declare variables as volatile if they have this behavior. To correctly handle those cases, your com iler has to give u most of its ho e of kno!ing ho! variables !ill be u dated during e6ecution. 5ince it is ossible to !rite code that uses those techniIues to u date a variable !hen une6 ected, the C com iler has to actually read a variable every time it is referenced unless it can #ro7e that no u date !ill touch that variable bet!een t!o oints in a rogram. Every function call otentially alters every variable in sco e, !ithin some limits, such as the assum tion that non-volatile, non-global variables are unaffected. $ll data assed to a

function in another module through a ointer not declared const must be re-read after the function call. That ha ens often in large ro"ects. :hat about Haskell< Haskell is 1la?y and urely referentially trans arent1. -f you ass a value to a function, it !ill not be u dated. That means that 4HC can assume that. 5 ecifically, there is never a need to co y a value !hen it is assed into a function, or ever re-read it. $lso, a function !hich takes a list and returns art of that list hasn1t co ied anything. 5ince no u date is ossible, there is no harm in referencing the original. That1s a big savings in memory, !hich translates into less memory reads and less age faults. $lso, since the order of evaluation is unim ortant to the rogrammer, the com iler can determine the fastest order and reshuffle the code and memory usage. 2ther things make Haskell code fast. 7irst, Haskell1s la?iness adds an e6tra kick to the s eed, since some code is never e6ecuted. 5econd, there are only a fe! ieces to Haskell# functions, if-then-else, olymor hic ty es, e6ce tions, the -2 code, and a garbage collector. 9ost library list functions are built on foldr or a variant, if they do any real !ork at all. This is a very small number of ieces, and that makes Haskell easy to com ile and o timi?e. 7inally, 4HC does cross-module o timi?ation, even for library functions, something im ossible in C. Contrast that to CFCDD, !ith any number of libraries, most of them re-com iled, and the only thing fast is memory mani ulation. -f you need memory mani ulation, C is !hat you use. Python makes code-!riting Iuick. /-5P makes logical mani ulation easy. Eava makes code safely ortable. Haskell is great (in my o inion) for the ma"or target of industry# big ro"ects !ith a lot of arts. 5econd, there is the source code itself. -f you don1t care about the order of e6ecution, you can avoid using synta6 to s ecify it. The best !ay to discover this is to try it yourself. -f you1re having trouble breaking your im erative habits, read other Haskell code until you can understand !hy it is so short. The e6am les in the ne6t section have been included for that ur ose. The source code of the Prelude itself is also a good lace to look.

,.2 Part II0 *eedback and /otes


-f you liked this tutorial, it came in handy, it hel ed you understand Haskell, or you think talk to much, !rite me at ethersonZyahoo.com. =ideo games and other gra hical a lications !ritten in Haskell can use H2 en4l and H2 en$/. To encourage this, .ave 9orra has !ritten a short tutorial on H2 en4/, although it is not currently online. :rite me or look him u if you1d like to see that tutorial. The 4entle -ntroduction Haskell, useful as a reference# htt #FF!!!.haskell.orgFtutorialF The Tour of the Haskell 5ynta6, also a good reference# htt #FF!!!.cs.ute .eduFcheonFcs3380F agesFhaskell-synta6.html

7inally, 4HC1s Hierarchical libraries, an e6cellent reference once you kno! the basics# htt #FF!!!.haskell.orgFghcFdocsFlatestFhtmlFlibrariesFinde6.html @ou should robably read the 4entle -ntroduction to Haskell and the Tour of the Haskell 5ynta6 thoroughly. Ho efully a lot more should make sense no!. There are a lot of little icky things in every rogramming language, and Haskell is no e6ce tion. Particularly, there are a fe! cases !here strictness is an issue, and it1s im ortant to kno! ho! Haskell1s synta6 is inter eted. 4ood luck. /et me kno! if there1s another tutorial - need to !rite, or about any bug in the big e6am les.

,.3 Part III0 %anting


:e1ve covered a lot of the basics of using Haskell, and the ne6t section has longer e6am les of Haskell code that go beyond toy rograms. -1d like to take the time to talk about !hy think Haskell is im ortant, !hy - !rote this tutorial, and !hat learning Haskell !as like for me. -f you !ant to get to the e6am les immediately, go ahead and ski to the ne6t section. .uring this tutorial, - refer to Haskell1s 1 o!er1. - am cribbing from an old eIuation about rogramming languages#
fle-ibilit# * $ontrol of 0etail = a $onstant

That statement should really be !ritten as follo!s#


fle-ibilit# * $ontrol of 0etail = power

Haskell has both more fle6ibility and more control than most languages. ;othing that - kno! of beats C1s control, but Haskell has everything C does unless you need to control s ecific bytes in memory. 5o - call Haskell o!erful, rather than "ust 1good1. - !rote this tutorial because Haskell !as very hard for me to learn, but no! - love it. - haven1t seen tutorials that addressed the difficulty that com uter science students usually face !ith Haskell. - had to take t!o semesters of college that included Haskell before - really got a gri on it, and - only assed the first because one of my friends kne! Haskell and hel ed me. ke t thinking that other eo le, maybe the haskell.org eo le, !ould !rite a tutorial aimed at C rogrammers, but it didn1t ha en. - understand !hy, no!. $s far as - can tell, Haskell is maintained and contributed to mostly by rofessors, and they have already learned /-5P or other functional languages. $lso, Haskell is not generally taught to !hiny undergrads that thro! a fit !hen faced !ith something this ne! and different. KT $ustin is some!hat of an e6ce tion, and out of my classmates, - !as the e6ce tion in actually liking it, let alone learning it. 5o a relatively small number of eo le have been in my osition, and it seems like none of them have s oken u . :ell, here it is. >Haskell is !ard?> >9ou can"t write code t!e wa( I know !ow?> >-( brain !urts?> >T!ere aren"t an( good references?> That1s !hat - said !hen - !as in college. There !ere good references, but they didn1t cover the real roblem# coders kno! C. :e, as students "ust getting through our second or third advanced com uter

science course, e6 ect seIuential behavior for code. -t isn1t good enough for a book to say that Haskell does not e6ecute commands in seIuence. :e can tell that. :hat !e don1t (and !hat - didn1t) understand is !hy on Earth you !ould bother coding in a language that !asn1t sort of like C, and ho! you !ould even think about it. :e could read all these tutorials and a fe! books about the synta6 of Haskell and ho! Haskell is la?y and has ure referential trans arency, but none of that hel s. :e don1t kno! ho! to ut functions together. :e don1t kno! !hat will be evaluated, and !e don1t kno! ho! the ieces of Haskell synta6 fit together. Haskell is so different from the industry standard (CFCDD) that !e can1t look at com licated Haskell code and understand it. And if we don"t2 Haskell will alwa(s be an academic language. 2f course, if a small horde of college kids start making little rograms in Haskell, the language !ill survive, and maybe there !ill be a com any that uses Haskell to make big games. - su ose there might be already. :ith 2 en4/ and 2 en$/ bindings, that1s a guarantee. >ut only if students are using it, not "ust rofessors. :hen - started this tutorial, !ondered !hy the Haskell eo le didn1t see this already. That1s okay, they1ve been busy making a !onderful and e6tremely o!erful language and libraries, and - thank them for it. Ho efully !ith good e6am les, a lications, and games. :ell, -1m done here. Thanks for reading all of this. 4ood luck !ith the big e6am les.

: 'ection 3I0 6)tended 6)am#les


:.1 Part I0 Intro to 6)am#les
This section covers the e6tended e6am les - have added to this tutorial. The entire set of e6am les can be do!nloaded as a .?i or .tar.b?% archive. $gain, here are the source files and te6t for all e6am les for this tutorial, including all those in the sections and the large e6am les at the end, ?i ed using b?i %# b?i % of sources, %&J, and ?i ed as a ?i # ?i of sources, 03J. /ists of the relevant files are at the beginning of each art. $s a reminder, for the e6am les in the sections, see the follo!ing#

E6am le5ectionsCode.hs E6am le5ectionsTry.t6t

The e6am les use concise notation !here the final a earance is clear, but this does not mean that it !ill be immediately clear to Haskell novices. Haskell encourages lengthy statements that can become difficult to com rehend, and - have attem ted to break these u into smaller com onents that can be easily identfied and labeled. There are t!o e6tra ieces of synta6 in the e6am les that - have not already covered in this tutorial. The first is the 1[1 o erator. -n some cases, - use the 1[1 o erator to avoid dee ly nested arentheses.
su @iste0J1, su @iste0J* :: :u a => &a' -> &Int' -> a su @iste0J1 nu s in0i$es = su ( ap (nu s 99) in0i$es)

su @iste0J* nu s in0i$es = su

ap (nu s 99) in0i$es

1[1 is a do-nothing o eratorP it1s only oint is to alter the recedence of the e6 ressions on its left and its right. -t takes t!o values as arameters and a lies the first the the second. This is useless, mathematically, but it can let a rogrammer avoid arenthesi?ing lengthy e6 ressions. - learned it from using H2 en4/, since many of the state altering functions take several lines of arameters. The second iece of synta6 is the effect of backIuotes, 1\1, !hich are belo! 1M1 on many keyboards. :hen laced around a function !hich acce ts t!o arameters, backIuotes make that function act like an o erator.
printIs7e berJ1, printIs7e berJ* :: (CQ a, 5AoB a) => &a' -> a -> I= () printIs7e berJ1 ite s ite = if ele ite ite s tAen put5tr@n U (sAoB ite ) ++ 4 is a e ber of tAe list;4 else put5tr@n U (sAoB ite ) ++ 4 is :=? a e ber of tAe list;4 printIs7e berJ* ite s ite = if ite Vele V ite s tAen put5tr@n U (sAoB ite ) ++ 4 is a e ber of tAe list;4 else put5tr@n U (sAoB ite ) ++ 4 is :=? a e ber of tAe list;4

1elem1 takes t!o arameters, a single item and a list of the same kind and returns True if the single item is resent in the list, other!ise 7alse. -n the second definition (1 rint-s9emberv%1), backIuotes are use to use \elem\ like an o erator bet!een its t!o arameters. - could have !ritten my e6am les !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 e6am les aren1t in order of im ortance. 5ki around if you like, or skim the source code for style hints. 5ome of the e6am les involve com licated to ics, but they are ho efully documented !ell enough that assing familiarity is sufficient.

:.2 Part II0 Calculating Pi


1 i1 is a builtin constant in Haskell, as it is in many languages. This e6am le demonstrates some Haskell techniIues by calculating i in various !ays. The easiest !ay to use this e6am le is to load the source into 4HCi and notice ho! long it takes each value 1 i'1, 1 i%1, and 1 i31 to evaluate the first time. The files#

E6am lePiCalc.hs

-n Haskell, 1 i1 is defined in the 17loat1 class here# The Prelude# the 17loat1 class 9uch of the math in the code !as taken from this age#

:iki edia1s article GCom uting PiG The values generated by the code differ slightly from the most accurate value ossible. -n t!o cases, the last digit is slightly off because the math used involves rounding the last digit. -n the case of 1 i'1, this is because greater accuracy is unattainable using that method !ithout e6cessive com utation. 2nce one of the constants has been evaluated, it !ill not be reevaluated if reIuested a second time. @ou can see this in 4HCi by noting that 1 i'1 takes several seconds or more to rint the first time, but virtually no time after that. This is an e6am le of la?y evaluation a lied to constants.

:.3 Part III0 -erge'ort 3ariations


This e6am le rovides the functions 1merge5ort'1, 1merge5ort%1, and 1merge5ort31 as !ell as some sim le test lists 1list'1, 1list%1, and 1list31. The easiest !ay to use this e6am le is to load the source into 4HCi and try the different sort functions on various lists. $lso try the function 1sort1 in .ata./ist for com arison. The files#

E6am le9erge5ort.hs

This is not ractical code, since the default 1sort1 function is efficient for lists, but the variants illustrate a lot of the basics of Haskell. The default sort function can be reached in source code by utting Gim ort .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 list se arately, then do a sim le merge o eration the makes one sorted list from the t!o sorted halves. Ho! do you sort the halves< >y running merge sort on them, too. This s litting continues 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 some o timi?ations that try to avoid as much recalculation as ossible. To s lit a list in half, you need its length. The first and sim lest variant calculates that for every call, !hich arguably uses some redundant com utation. The second variant tries to avoid this redundancy by assing around the length of the list and dividing it by % at ever call. This !ould result in some slightly lo sided merges, but no real loss of efficiency there. The gains !ould robably out!eigh the loss. The third variant goes overboard and tries an o timi?ation that is likely !orse than the second variant. This is an e6am le of a good idea !hich needs close e6amination. The third variant forms t!o halves by lacing individual items alternately into t!o lists. This avoids recalculating the length !ith each call and avoids assing an integer and doing math !ith each call. Ho!ever, about as much !ork is necessary to s lit the list in this manner as in the other methods, ossibly more.

:. Part I30 %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 to ics that !ill be unfamiliar for some students. The smaller e6am les above and in the other sections of the tutorial are aimed at broad audiences, but such good e6am les are not necessarily available for more com le6 demonstrations. $t the risk of alienating some readers, - have !ritten a com le6 e6am le covering regular e6 ressions, finite automata, Haskell1s module system, and !riting your o!n monads. This is a big e6am le and it covers a lot of ground. The files involved are#

E63Eto7$convert.7$.hs E63Eto7$convert;7$.hs E63Eto7$convert3E.hs E63Eto7$convert3Ev'.hs E63Eto7$convert3Ev%.hs E63Eto7$convert3Ev%monad.hs E63Eto7$convert3Ev3.hs E63Eto7$convert3Ev3monad.hs E63Eto7$e6am leTests.t6t E63Eto7$e6ecution.hs E63Eto7$main.hs E63Eto7$ty es.hs

The code in this e6am le takes a string and arses it according to a subset of the P25-C standard for regular e6 ressions (3Es), converting it into a structure suited for testing in ut. That structure is then converted to a non-deterministic finite automata (;7$) !hich !ill acce t and re"ect eIuivalent in uts. 7inally, that ;7$ is converted to a deterministic finite automata (.7$), although no great effort is made to minimi?e the number of states. -f you don1t kno! !hat either regular e6 ressions or finite automata are, these are covered in detail in any undergraduate com uter science education. -f you are currently in school, you !ill get detailed instruction on them, robably soon. -f not, these are to ics you can learn at your leisure. - do not yet kno! if this e6am le can be understood !ithout a com lete kno!ledge of the material. Please send me feedback about that. :hether or not you are familiar !ith these conce ts, you can test the code !ith the e6am les in E63Eto7$e6am leTests.t6t. 7irst you give a regular e6 ression in P25-C notation as an in ut, then you re eatedly give strings to test against it. Kse Ctrl-C to Iuit. The statements are rinted as soon as each o eration is done, so if a statement fails to a ear, that o eration !ent into an infinite loo . This occurs in some cases !ith the first im lementation of running an ;7$ and is difficult to revent in any im lementation of running a regular e6 ression directly. 7or that reason, and because .7$s can be e6ecuted more Iuickly, in ractice 3Es (and ;7$s) are converted to .7$s before use. 9y im lementation uses a counter to test for dee ly recursing e6ecution so - can return a value indicating failure.

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


The 1ty es.hs1 file for this e6am le rovides the ty es used in the rest of the files. -n addition, the module rovides functions that validate members of those ty es and functions !hich com ute useful information from members of those ty es. This is the only module !hich does not include any other modules from the e6am le. 7iles#

E63Eto7$ty es.hs

The im ort statements in this file (and the rest) do not bring into sco e everything from the standard modules they im ort. -nstead, they only include the functions and ty es used in the code. .oing this hel s track !hat functions are used !here and revents accidental clashes or similarities bet!een names. The comments in this file also include a summary of the P25-C rules im lemented.

:., Part 3I0 %egular 6)#ressions and *inite Automata0 'tring to %62 and -onads
The base file for this art of the e6am le includes and re-e6 orts three functions. There is one for each version im lemented of the method to convert a string to the P25-C regular e6 ression that it re resents. 7iles#

E63Eto7$convert3E.hs E63Eto7$convert3Ev'.hs E63Eto7$convert3Ev%.hs E63Eto7$convert3Ev%monad.hs E63Eto7$convert3Ev3.hs E63Eto7$convert3Ev3monad.hs

The first method, im lemented in 1convert3Ev'.hs1, is a set of functions !hich !ork on the in ut string. They ass it around along !ith the ieces of regular e6 ressions under construction. There is nothing !rong !ith this method, and in fact - only added the other methods as a final touch to the e6am le. 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 in ut. This 1 assing for!ard1 nature made the conversion suitable for reim lementation as a 9onad. =ersions % and 3 of this conversion sho! ho! you can make your o!n monad. @ou create the ty e, not an intuitive task !hen you need to carry a state. @ou then !rite the instance declaration, the accessor functions, and functions !hich com ose those accessors. :hy use monads for this task< ;ote the ty es of the recursive functions#
$onJert5MCouter1 :: 5trin6 -> 7#Me6C-p -> 7a#be (7#Me6C-p, 5trin6) $onJert5Quare>lo$81 :: 5trin6 -> 7a#be (7#Me6C-pIte , 5trin6) $onJert:u ber>lo$81 :: 5trin6 -> 7a#be (Int, Int, 5trin6)

-n each case, the in uts 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 se arate our changes to state, assed for!ard to the ne6t function called, from our return values, assed u !ard to the calling function. 5ince a 5tring is assed for!ard in every case, that !ill be the monad1s state, its internal value. The rest of the data !ill be normal return values. The functions have almost e6actly the same structure, but the code is clearer. The instance !as very hard for me to !rite. There are t!o issues, the first being that the synta6 for -nstance declarations is tricky to find. The second is that, even armed !ith the ty e of (UUO), the functions are difficult to !rite. /et1s analy?e them. Here1s !hat 4HCi says about (UUO)#
/relu0e> :t (>>=) (>>=) :: (7ona0 ) => a -> (a -> b) -> b

$t least !e can tell that it has t!o arameters, one of ty e 1m a1 and one of ty e 1(a -U m b)1. The immediate Iuestion, if you can understand the ty es, is, G:hy is the monad ty e assed a ty e variable as if it is a ty e constructor<G -t seems like, even if you define a ty e that doesn1t take a variable, if you define it as an instance of 9onad, it has to take a ty e variable. The truth is that a monad must take a ty e variable. This variable ty e is used to ass back results. :hat is not mentioned any!here is ho! to handle assing a state for!ard. $ monad data ty e does not contain a state. -f you use a state, your monad ty e must instead be a function !hich takes a state and then returns it. -n this !ay, the function describes ho! to transform a state. 7or instance, the follo!ing code does not !ork#
neBt#pe MC a8er* a = MC* (5trin6, a)

:here things fail is that you !ill find no !ay for the bind o eration (UUO) to take the e6isting state as an in ut. This is not fi6ed by altering the bind method or the function to be bound, but only by altering the ty e of the monad itself so that a later instance takes the ne! state as a arameter. This is not intuitive for me and not something that - can do !ithout the e6am les - listed. @ou also have to !ra u your ty e for a 9onad in a 1ne!ty e1 declaration (or a 1data1 declaration) so that it !orks in an -nstance declaration. Haskell !ill not let you define an instance for a ty e other than those. :hen - !as !orking !ith this e6am le on monads, - used a lot of hel from here# htt #FF!!!.engr.mun.caFMtheoF9iscFhaskellNandNmonads.htm The third version is very similar to the second, but sho! ho! some e6tra access functions can make code sim ler. >oth files make use of a se arate file to store their ty es. The e6 ort list for those sub-modules s ecifically fails to e6 ort the constructor for the monad ty e. This forces the functions outside that sub-module to only modify and use the monad using the

e6 orted accessor and run functions. This is done to make the data ty e abstract and kee code clean. -t is !orth noting that even !ith the data ty e in a se arate file, the code is longer !hen im lemented 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 gains increase !hen using monads in cases for !hich they are a ro riate. 9any of the gains come from lack of errors in carrying state for!ard, !hich is most of the oint in the first lace.

:.: Part 3II0 %egular 6)#ressions and *inite Automata0 Con7ersion and 6)ecution
The remaining conversion files for this e6am le im lement some standard algorithms for converting 3Es to ;7$s and ;7$s to .7$s. The code is com le6 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. Ho efully, this !ill hel the reader follo! along. 7iles#

E63Eto7$convert.7$.hs E63Eto7$convert;7$.hs

The e6ecution file for this e6am le uses multi le methods to test in ut strings against the resulting structure from each oint in the conversion rocess. The key distinctions are that some methods track the set of reachable states simultaneously, acce ting !hen any reachable state !ould acce t, and other methods make a se arate recursive call for all branches. The branching method is rone to infinite loo s. The fact that 3Es and ;7$s branch, !hile the end result, .7$s, do not branch, illustrates !hy this conversion is usually erformed. 7iles#

E63Eto7$e6ecution.hs

-n the main rogram for this e6am le, these e6ecution methods are ordered and dis layed. E6tensive use is made of basic o erations in the -2 monad, and this file can serve as an e6am le for that as !ell, articularly the need to flush buffers after !rites !hich do not end in a ne!line. 7iles#

E63Eto7$main.hs

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


The final e6am le, currently, is an abbreviated demonstration of list com rehensions and the 1data1 data ty e declaration. The rogram solves boolean eIuations in con"unctive normal form !ith t!o variables each, also called %C;7. This is !idely kno!n as a s ecial case of the ;P-Hard C;7 roblem. The files#

E6am le%C;7.hs

The source code for this e6am le indicates several !ays to e6 and on it.

Eric Etheridge, ethersonZyahoo.com

Potrebbero piacerti anche