[Finish comments for chapter 2 Bryan O'Sullivan **20080724005512] { addfile ./en/snippets/ch02-cat.xml addfile ./en/snippets/ch02-wc.xml addfile ./examples/ch02/WC.hs hunk ./en/ch02-starting.xml 6 - As you read this chapter and the few that follow, it's good to - keep in mind that early on, we will sometimes introduce ideas in - restricted, simplified form. Haskell is a deep language, and - presenting every aspect of a given subject all at once is likely - to prove overwhelming. As we build a solid foundation in Haskell, - we'll expand upon these initial explanations. + As you read the early chapters of this book, keep in + mind that we will sometimes introduce ideas in restricted, + simplified form. Haskell is a deep language, and presenting every + aspect of a given subject all at once is likely to prove + overwhelming. As we build a solid foundation in Haskell, we will + expand upon these initial explanations. hunk ./en/ch02-starting.xml 55 - recommend using whatever is the newest - version available for your platform. If you're using Windows or - Mac OS X, you can get started easily and quickly using a - prebuilt installer. To obtain a copy of &GHC; for these - platforms, visit the &GHC; + recommend using the newest version + available for your platform. If you're using Windows or Mac OS + X, you can get started easily and quickly using a prebuilt + installer. To obtain a copy of &GHC; for these platforms, visit + the &GHC; hunk ./en/ch02-starting.xml 82 - The interactive interpreter for &GHC; is a program named - &ghci;. It lets us enter and evaluate Haskell expressions, - explore modules, and debug our code. If you're familiar with - Python or Ruby, &ghci; is somewhat similar to + The interactive interpreter for &GHC; is a program + named &ghci;. It lets us enter and evaluate Haskell + expressions, explore modules, and debug our code. If you are + familiar with Python or Ruby, &ghci; is somewhat similar to hunk ./en/ch02-starting.xml 89 - The &ghci; command is not a complete interpreter - for all of Haskell. We typically cannot copy some code out of a - Haskell source file and paste it into &ghci;: it only accepts - expressions and some other directives. In this respect, it's - more restrictive than, say, the interactive Python interpreter, - which can accept all Python code. + + The ghci command has a narrow focus + + We typically cannot copy some code out of a + Haskell source file and paste it into &ghci;. This does not + have a significant effect on debugging pieces of code, but it + can initially be surprising if you are used to, say, the + interactive Python interpreter. + hunk ./en/ch02-starting.xml 99 - On Unix-like systems, we run &ghci; as a command in a shell - window. On Windows, it's available as a menu item accessible - from the Start Menu. For example, if you installed using the - &GHC; installer on Windows XP, you should go to All - Programs, then GHC; you'll then see - &ghci; in the list. (See for a + On Unix-like systems, we run &ghci; as a command + in a shell window. On Windows, it's available via the Start + Menu. For example, if you installed using the &GHC; installer + on Windows XP, you should go to All Programs, + then GHC; you will then see &ghci; in the list. + (See for a hunk ./en/ch02-starting.xml 109 - version 6.6.1 run on a Linux box. More recent versions print a - shorter banner. + version 6.8.3 on a Linux box. hunk ./en/ch02-starting.xml 113 - ___ ___ _ - / _ \ /\ /\/ __(_) - / /_\// /_/ / / | | GHC Interactive, version 6.6.1, for Haskell 98. -/ /_\\/ __ / /___| | http://www.haskell.org/ghc/ -\____/\/ /_/\____/|_| Type :? for help. - +GHCi, version 6.8.3: http://www.haskell.org/ghc/ :? for help hunk ./en/ch02-starting.xml 127 - If you enter :? at the &ghci; prompt, it will - print a long help message. + If you enter :? at the &ghci; + prompt, it will print a long help message. hunk ./en/ch02-starting.xml 164 + + We can now use the functionality of the + Data.Ratio module, which lets us work with rational + numbers (fractions). hunk ./en/ch02-starting.xml 224 - Haskell's only unary operator, and we can't mix it with infix + Haskell's only unary operator, and we cannot mix it with infix hunk ./en/ch02-starting.xml 229 - If we want to use the unary minus near an infix operator, - we must wrap the expression it applies to in + If we want to use the unary minus near an infix + operator, we must wrap the expression it applies to in hunk ./en/ch02-starting.xml 235 - Most of the time, we can omit - white space from expressions, and Haskell will parse them as we - intended. But not always. Here's an expression that + This avoids a parsing ambiguity. When we apply a function + in Haskell, we write the name of the function, followed by its + argument, for example f 3. If we did not need to + wrap a negative number in parentheses, we would have two + profoundly different ways to read f-3: it could + be either apply the function f to + the number -3, or subtract the + number 3 from the variable + f. + + Most of the time, we can + omit white space (blank characters such as + space and tab) from expressions, and Haskell will parse them + as we intended. But not always. Here is an expression that hunk ./en/ch02-starting.xml 253 - And here's one that seems similar to the + And here is one that seems similar to the hunk ./en/ch02-starting.xml 260 - +- as a single operator. Haskell lets us - define new operators (a subject that we'll return to later), - but we haven't defined this one. Once again, a few - parentheses get us and &ghci; looking at the expression in the - same way. + *- as a single operator. Haskell lets us + define new operators (a subject that we will return to later), + but we haven't defined *-. Once again, a + few parentheses get us and &ghci; looking at the expression in + the same way. hunk ./en/ch02-starting.xml 271 - operators at any time. This isn't some kind of esoteric - language feature; we'll see quite a few user-defined operators + operators at any time. This is not some kind of esoteric + language feature; we will see quite a few user-defined operators hunk ./en/ch02-starting.xml 282 - &True; and &False;. The language uses C-influenced operators - for working with Boolean values. + &True; and &False;. The capitalization of these names is + important. The language uses C-influenced operators for + working with Boolean values: (&&) + is logical and, and (||) + is logical or. hunk ./en/ch02-starting.xml 290 - Here, (&&) is logical - and, and (||) is logical - or. - - Unlike some other languages, Haskell does - not treat the - number zero as synonymous with False, nor - does it consider any non-zero value to be True. + While some programming languages treat the + number zero as synonymous with False, + Haskell does not, nor does it consider a non-zero value to be + True. hunk ./en/ch02-starting.xml 297 - Once again, we're faced with a substantial-looking error - message. In brief, it tells us that the Boolean type, Bool, - is not a member of the family of numeric types, - Num. The error message is rather long because - &ghci; is pointing out the location of the problem, and - hinting at a possible change we could make that might fix the - problem. + Once again, we are faced with a + substantial-looking error message. In brief, it tells us that + the Boolean type, Bool, is not a member of the + family of numeric types, Num. The error message + is rather long because &ghci; is pointing out the location of + the problem, and hinting at a possible change we could make + that might fix the problem. + + Here is a more detailed breakdown of the error + message. + + + + No instance for (Num Bool) + tells us that &ghci; is trying to treat the numeric value + 1 as having a Bool type, but it + cannot. + + + arising from the literal + `1' indicates that it was our use of + the number 1 that caused the problem. + + + In the definition of `it' + refers to a &ghci; short cut that we will revisit in a few + pages. + + hunk ./en/ch02-starting.xml 328 - Remain dauntless in the face of error messages + Remain fearless in the face of error messages hunk ./en/ch02-starting.xml 330 - An important guideline here is one that we'll - be repeating over and over throughout the early sections of - this book. If you run into problems or error messages that - you do not yet understand, don't panic. - Early on, all you have to do is figure out enough to make - progress through a problem. As you acquire experience, parts - of error messages that now seem obscure will become easier - to follow. + We have an important point to make here, which + we will repeat throughout the early sections of this book. + If you run into problems or error messages that you do not + yet understand, don't panic. Early on, + all you have to do is figure out enough to make progress on + a problem. As you acquire experience, you will find it + easier to understand parts of error messages that initially + seem obscure. hunk ./en/ch02-starting.xml 349 - similar to those used in C and languages influenced by - C. + similar to those used in C and the many languages it has + influenced. hunk ./en/ch02-starting.xml 354 - There's one exception: the is not - equal to operator is (/=) - (somewhat visually similar to the mathematical ¬Equal; - operator), not the (!=) you might expect - from a language that borrows many other operators from - C. + One operator that differs from its C counterpart + is is not equal to. In C, this is written as + !=. In Haskell, we write + (/=), which resembles the ¬Equal; + notation used in mathematics. hunk ./en/ch02-starting.xml 362 - Also, where C and Perl use ! for - logical negation, Haskell uses the not - function. + Also, where C-like languages often use + ! for logical negation, Haskell uses the + not function. hunk ./en/ch02-starting.xml 373 - Like other languages that use infix notation to - write some expressions, Haskell has a notion of + Like written algebra and other programming + languages that use infix operators, Haskell has a notion of hunk ./en/ch02-starting.xml 376 - group parts of an expression, and precedence allows us to - omit a few parentheses. For example, the multiplication - operator has a higher precedence than the addition operator, - so Haskell treats the following two expressions as - equivalent. + group parts of an expression, and precedence allows us to omit + a few parentheses. For example, the multiplication operator + has a higher precedence than the addition operator, so Haskell + treats the following two expressions as equivalent. hunk ./en/ch02-starting.xml 383 - Haskell assigns numeric precedence values to operators, - with 1 being the lowest precedence and 9 the highest. A - higher-precedence operator gets parsed before a + Haskell assigns numeric precedence values to + operators, with 1 being the lowest precedence and 9 the + highest. A higher-precedence operator is applied before a hunk ./en/ch02-starting.xml 388 - :type command. + :info command. hunk ./en/ch02-starting.xml 392 - Since (*) has a higher precedence - than (+), we can now see why 1 + 4 - * 4 is parsed as 1 + (4 * 4), and not + The information we seek is in the line + infixl 6 +, which indicates that + the (+) operator has a precedence of 6. + (We will explain the other output in a later chapter.) + The infixl 7 * tells us that the + (*) operator has a precedence of 7. Since + (*) has a higher precedence than + (+), we can now see why 1 + 4 * + 4 is evaluated as 1 + (4 * 4), and not hunk ./en/ch02-starting.xml 405 - multiple uses of an operator is parsed from left to right, or + multiple uses of an operator is evaluated from left to right, or hunk ./en/ch02-starting.xml 409 - above. A right associative operator would be displayed with + above. A right associative operator is displayed with hunk ./en/ch02-starting.xml 412 - The combination of precedence and associativity rules are - usually referred to as fixity + &basics.ghci:caret; + + The combination of precedence and associativity + rules are usually referred to as fixity hunk ./en/ch02-starting.xml 428 - But its coverage of mathematical constants is not great, - as we can quickly see. Let's see if Euler's number, - e, is available. + But its coverage of mathematical constants is + not comprehensive, as we can quickly see. Let us look for + Euler's number, e. hunk ./en/ch02-starting.xml 434 - Oh well. + Oh well. We have to define it ourselves. hunk ./en/ch02-starting.xml 439 - If the above not in scope error message - seems a little daunting, don't worry. All it means is that - there is no variable defined with the name + If the above not in scope error + message seems a little daunting, do not worry. All it means + is that there is no variable defined with the name hunk ./en/ch02-starting.xml 450 - This is a call to the base-e - exponential function, exp, and our first - example of calling a function in Haskell. While languages - like Python require parentheses around the arguments to a - function, Haskell does not. + This is an application of the exponential + function, exp, and our first example of + applying a function in Haskell. While languages like Python + require parentheses around the arguments to a function, + Haskell does not. hunk ./en/ch02-starting.xml 456 - With e defined, we can use it - in arithmetic expressions. + With e defined, we can now + use it in arithmetic expressions. The + (^) exponentiation operator that we + introduced earlier can only raise a number to an integer + power. To use a floating point number as the exponent, we use + the (**) exponentiation operator. hunk ./en/ch02-starting.xml 468 - The syntax for &let; that &ghci; accepts is not the same - as we would use in a normal Haskell program. We'll see the - normal syntax in . + The syntax for &let; that &ghci; accepts is + not the same as we would use at the top level + of a normal Haskell program. We will see the normal syntax + in . hunk ./en/ch02-starting.xml 476 - Navigating the thicket of fixity rules + Dealing with precedence and associativity rules hunk ./en/ch02-starting.xml 478 - It's sometimes better to leave at least some + It is sometimes better to leave at least some hunk ./en/ch02-starting.xml 489 - Here's a cautionary example of mixing different operators - of the same fixities: (*) and - (/). The following two expressions give - subtly different results. - - &basics.ghci:grouping; - - When deciding whether to use parentheses, you can probably - rely on yourself and your readers to remember the language's - precedence rules for the most common arithmetic and logical - operators: (||) is 2; - (&&) is 3; - (+) and (-) are - 6; while (*) and - (/) are 7. For - associativities and for other operators, it's not often wise - to assume that readers will remember the rules, so parentheses - are often safest. + There is no need to remember all of the + precedence and associativity rules numbers: it is simpler to + add parentheses if you are unsure. hunk ./en/ch02-starting.xml 543 - Some languages permit the last element in a list to be - followed by an optional trailing comma before a closing + Some languages permit the last element in a list + to be followed by an optional trailing comma before a closing hunk ./en/ch02-starting.xml 546 - trailing comma, you'll get a parse error. + trailing comma (e.g. [1,2,]), you'll get a parse + error. hunk ./en/ch02-starting.xml 555 - All elements of a list must be of the same type. + All elements of a list must be of the same type. + Here, we violate this rule: our list starts with two + Bool values, but ends with a string. hunk ./en/ch02-starting.xml 567 - range notation, Haskell will fill in the - contents of the list for us. + enumeration notation, Haskell will fill in + the contents of the list for us. hunk ./en/ch02-starting.xml 572 - Here, the .. characters denote a range. - We can only use range notation for types whose elements we can - enumerate. Range notation makes no sense for rational numbers, - for example, because there is not a countable number of - rationals. + Here, the .. characters denote + an enumeration. We can only use this + notation for types whose elements we can enumerate. It makes no + sense for text strings, for instance: there is not any sensible, + general way to enumerate ["foo".."quux"]. hunk ./en/ch02-starting.xml 582 - When we write a range, we can optionally specify - the size of the step to use by giving the first two elements, - followed by the value at which to stop generating the - range. + When we write an enumeration, we can optionally + specify the size of the step to use by providing the first two + elements, followed by the value at which to stop generating the + enumeration. hunk ./en/ch02-starting.xml 590 - sensibly missing the end point of the range, because it isn't an - element of the series we defined. + sensibly missing the end point of the enumeration, because it + isn't an element of the series we defined. hunk ./en/ch02-starting.xml 593 - We can omit the end point of a range. If the type we're - enumerating has an upper bound on its values (or a lower bound - if the step is negative), that bound will be the end point of - the range. Otherwise, the range will continue indefinitely. - For example, if you type [1..] at the &ghci; - prompt, you'll have to interrupt or kill &ghci; to get it to - stop printing an infinite succession of ever-larger - numbers. + We can omit the end point of an enumeration. If a + type doesn't have a natural upper bound, this + will produce values indefinitely. For example, if you type + [1..] at the &ghci; prompt, you'll have to + interrupt or kill &ghci; to stop it from printing an infinite + succession of ever-larger numbers. If you are tempted to do + this, type C to + halt the enumeration. We will find later on that infinite lists + are often useful in Haskell. hunk ./en/ch02-starting.xml 606 - Beware ranges of floating point numbers + Beware enumerating floating point numbers hunk ./en/ch02-starting.xml 612 - Behind the scenes, the Haskell implementation is - converting the floating point numbers into integers, - enumerating the range as integers, then turning them back into - floating point numbers. + Behind the scenes, to avoid floating point + roundoff problems, the Haskell implementation enumerates from + 1.0 to 1.8+0.5. hunk ./en/ch02-starting.xml 616 - While this is peculiar, there's worse in store. The range - [0,0.1..1] steps in increments of 0.1 - between zero and one, but the number of elements in the list - depends on the amount of rounding error in the - implementation's representation of floating point numbers: you - will probably get a list of eleven - elements, but you might get ten. - - Because of these limitations, range notation over floating - point numbers is not really safe to use. + Using enumeration notation over floating point + numbers can pack more than a few surprises, so if you use it + at all, be careful. Floating point behavior is quirky in all + programming languages; there is nothing unique to Haskell + here. hunk ./en/ch02-starting.xml 632 - More basic is the (:) operator, which - adds an element to the front of a list. This is pronounced - cons (short for + More basic is the (:) + operator, which adds an element to the front of a list. This + is pronounced cons (short for hunk ./en/ch02-starting.xml 638 + + You might be tempted to try writing [1,2]:3 + to add an element to the end of a list, but &ghci; will reject + this with an error message, because the first argument of + (:) must be an element, and the second + must be a list. hunk ./en/ch02-starting.xml 654 - A text string is surrounded by double quotes. + A text string is surrounded by double + quotes. hunk ./en/ch02-starting.xml 659 - As in many languages, we can represent - hard-to-print characters by escaping them. - Haskell's escape characters and escaping rules follow the widely - used conventions established by the C language. For example, + As in many languages, we can represent hard-to-see + characters by escaping them. Haskell's escape + characters and escaping rules follow the widely used conventions + established by the C language. For example, hunk ./en/ch02-starting.xml 669 - Haskell makes a distinction between single characters and - text strings. A single character is enclosed in single - quotes. + The putStrLn function prints a + string. + + Haskell makes a distinction between single + characters and text strings. A single character is enclosed in + single quotes. hunk ./en/ch02-starting.xml 678 - In fact, a text string is simply a list of individual - characters. Here's a painful way to write a short string, which - &ghci; gives back to us in a more familiar form. + In fact, a text string is simply a list of + individual characters. Here's a painful way to write a short + string, which &ghci; gives back to us in a more familiar + form. hunk ./en/ch02-starting.xml 685 + The empty string is written "", and is a + synonym for []. + + &basics.ghci:emptystring; + + Since a string is a list of characters, we can use the regular + list operators to construct new strings. + + &basics.ghci:newstring; + hunk ./en/ch02-starting.xml 749 - That it variable is wonderfully handy - when we want to use the result of the prior expression in a new - expression. + That it variable is a handy + &ghci; shortcut. It lets us use the result of the expression + we just evaluated in a new expression. hunk ./en/ch02-starting.xml 756 - change your environment if the evaluation fails. A successful - evaluation will only change either the variable you specify, - or it if you didn't name a variable to - change. This lets you write potentially bogus expressions - with something of a safety net. + change the value of it if the evaluation + fails. This lets you write potentially bogus expressions with + something of a safety net. hunk ./en/ch02-starting.xml 764 - expression we typed, and this gives us a fairly decent - environment for interactive experiments, where the cost of - mistakes is very low. Take advantage of the opportunity to - make cheap, plentiful mistakes when you're exploring the - language! + expression we typed, we gain a decent way to experiment + interactively: the cost of mistakes is very low. Take + advantage of the opportunity to make cheap, plentiful mistakes + when you're exploring the language! hunk ./en/ch02-starting.xml 776 - Integer, and is unbounded; only your system's - memory capacity limits the size of the integers it can - represent. + Integer. The size of an Integer value + is bounded only by your system's memory capacity. hunk ./en/ch02-starting.xml 780 - integers. + integers. To construct a rational number, we use the + (%) operator. The numerator is on the + left, the demoninator on the right. hunk ./en/ch02-starting.xml 786 + For convenience, &ghci; lets us abbreviate many commands, so + we can write :m instead of + :module to load a module. + hunk ./en/ch02-starting.xml 793 - might infer that a Ratio must need to have values - of type Integer as both numerator and denominator. - Sure enough, if we try to construct a Ratio where - the numerator and denominator are of different types, or of the - same non-integral type, &ghci; complains. + might guess that a Ratio must have values of type + Integer as both numerator and denominator. Sure + enough, if we try to construct a Ratio where the + numerator and denominator are of different types, or of the same + non-integral type, &ghci; complains. hunk ./en/ch02-starting.xml 801 - Although it's initially useful to have + Although it is initially useful to have hunk ./en/ch02-starting.xml 803 - every expression we enter, this is a facility we'll quickly - outgrow: after a while, we'll often know what type we expect an + every expression we enter, this is a facility we will quickly + outgrow. After a while, we will often know what type we expect an hunk ./en/ch02-starting.xml 822 - - Exercises + Why are the types reported for these two expressions + different? hunk ./en/ch02-starting.xml 825 - - - - Foo? - - - - + &types.ghci:different; + + Haskell has several numeric types. For example, a literal + number such as 1 could, depending on the + context in which it appears, be an integer or a floating point + value. When we force &ghci; to evaluate the expression 3 + + 2, it has to choose a type so that it can print the + value, and it defaults to Integer. In the second + case, we ask &ghci; to print the type of the expression without + actually evaluating it, so it does not have to be so specific. + It answers, in effect, its type is numeric. We + will see more of this style of type annotation in . hunk ./en/ch02-starting.xml 840 - - Conclusion + + A simple program hunk ./en/ch02-starting.xml 843 - In this chapter, we've seen how to install &GHC; for our - environment. We then went on to interactively explore some - basic Haskell concepts using &ghci;, the interpreter bundled with - &GHC;. We saw how to evaluate simple expressions. + Let's take a small leap ahead, and write a small program + that counts the number of lines in its input. Don't expect to + understand this yet; it's just fun to get our hands dirty. In a + text editor, enter the following code into a file, and save it + as WC.hs. hunk ./en/ch02-starting.xml 849 - We dipped a toe into the water of typing. + &WC.hs:main; + + Find or create a text file; let's call it + quux.txt + Incidentally, what do these cities have in + common? + . + + &ch02-cat; + + From a shell or command prompt, run the following + command. + + &ch02-wc; + + We have successfully written a simple program that interacts + with the real world! In the chapters that follow, we will + successively fill the gaps in our understanding until we can + write programs of our own. + hunk ./en/ch02-starting.xml 870 - We also had drilled into us the notion that we don't need to - understand, or be intimidated by, every single gripe that &ghci; - throws our way. We'll do just fine with a shallow understanding - initially, and rely on practice and more reading to round out - our knowledge. Onwards! + + Exercises hunk ./en/ch02-starting.xml 873 + + + + Enter the following expressions into + &ghci;. What are their types? + + + 5 + 8 + + + 3 * 5 + 8 + + + 2 + 4 + + + (+) 2 4 + + + sqrt 16 + + + succ 6 + + + succ 7 + + + pred 9 + + + pred 8 + + + sin (pi / 2) + + + truncate pi + + + round 3.5 + + + round 3.4 + + + floor 3.7 + + + ceiling 3.3 + + + + + + + From &ghci;, type :? to print some + help. Define a variable, such as let x = 1, + then type :show bindings. What do you see? + + + + + The words function counts the + number of words in a string. Modify the + WC.hs example to count the number of + words in a file. + + + + + Modify the WC.hs example again, + to print the number of characters in a file. + + + hunk ./en/snippets/ch02-cat.xml 1 +$ cat quux.txt +Teignmouth, England +Paris, France +Ulm, Germany +Auxerre, France +Brunswick, Germany +Beaumont-en-Auge, France +Ryazan, Russia + + hunk ./en/snippets/ch02-wc.xml 1 +$ runghc WC < quux.txt +7 + hunk ./examples/ch02/WC.hs 1 +{-- snippet main --} +main = interact wordCount + where wordCount input = show (length (lines input)) ++ "\n" +{-- /snippet main --} + hunk ./examples/ch02/basics.ghci 25 -2+3 +2*3 hunk ./examples/ch02/basics.ghci 29 -2+-3 +2*-3 hunk ./examples/ch02/basics.ghci 33 -2+(-3) +2*(-3) hunk ./examples/ch02/basics.ghci 126 -"foo" ++ "bar" -[] ++ [1,2,3] ++ [4] +[3,1,3] ++ [3,7] +[] ++ [False,True] ++ [True] hunk ./examples/ch02/basics.ghci 140 -"Here's a newline -->\n<-- See?" -putStr "Here's a newline -->\n<-- See?" +putStrLn "Here's a newline -->\n<-- See?" hunk ./examples/ch02/basics.ghci 163 +[10,9..1] hunk ./examples/ch02/basics.ghci 179 +--# emptystring +"" == [] + +--# newstring +'a':"bc" +"foo" ++ "bar" + hunk ./examples/ch02/basics.ghci 194 +--# caret +:info (^) + hunk ./examples/ch02/types.ghci 1 -:m Data.Ratio - hunk ./examples/ch02/types.ghci 25 +:m +Data.Ratio hunk ./examples/ch02/types.ghci 44 +--# different +3 + 2 +:type it +:type 3 + 2 + hunk ./web/realworldhaskell.conf 7 - CustomLog logs/haskell-access_log full + CustomLog logs/haskell-access_log combined }