[More rewriting of chapter 2. Bryan O'Sullivan **20071002074442] { hunk ./en/ch02-starting.xml 192 - similarly to familiar languages like C and Python. + similarly to familiar languages like C and Python: we write + expression in infix form, where an + operator appears between its operands. hunk ./en/ch02-starting.xml 198 + Operators are normal Haskell functions; the infix style of + writing an expression is just a convenience. + hunk ./en/ch02-starting.xml 204 - (^) is the exponentiation - operator. We'll be talking more about exponentiation - in . + (^) is the integer exponentiation + operator. hunk ./en/ch02-starting.xml 212 - When we write operators by themselves, we'll usually - write them surrounded by parentheses, for example + When we write an operator by itself, we'll usually + write it surrounded by parentheses, for example hunk ./en/ch02-starting.xml 215 - treating an operator as a function. + writing an operator as an ordinary function. hunk ./en/ch02-starting.xml 444 - - Aside: the many faces of exponentiation - - Is it too early to introduce this? Does it disrupt the - flow? - - Mathematicians have three different ways of - looking at exponentiation, and Haskell has a specific operator - for each one. - - The first way of looking at exponentiation is to multiply - a number a by itself a given number - n of times. Here, the base - a can be any number, but the exponent - n must be an integer, and it must be - non-negative. - - &basics.ghci:intpower; - - Haskell's exponentiation operators follow the convention - that a number raised to the zeroth power is one. This is why - the restriction on the exponent is that it must be - non-negative, and not that it must be positive. - - &basics.ghci:exponent.zero; - - Haskell's type system enforces for us the requirement that - the exponent be an integer. If we try using a fractional - exponent, &ghci; will report a type error, telling us that it - expects an integral value here. - - &basics.ghci:exponent.bad; - - The second mathematical definition of - exponentiation works for both positive and negative integer - exponents. Where a positive exponent multiplies the base by - itself repeatedly, a negative exponent divides the number one - by the base repeatedly. If the base is zero, a negative - exponent thus leads to division by zero. - - &basics.ghci:exponent.neg; - - Finally, we have an operator that is defined for - real numbers, (**). - - &basics.ghci:exponent.float; - - hunk ./en/ch02-starting.xml 456 - Look at that error message; it's detailed, and mentions a - lot of concepts we haven't covered yet. We're new to Haskell! - How are we supposed to interpret all of that? The first thing - we must do is take a deep breath and not worry about the - details. + Look at that error message; it's detailed, and + mentions a lot of concepts we haven't covered yet. The best way + to start dealing with it is to not worry early on about the + details. The error messages that &GHC; produces can be daunting + to newcomers, but take heart. As you become more familiar with + Haskell, you'll acquire enough understanding to interpret error + messages more easily. hunk ./en/ch02-starting.xml 464 - If we step back and gloss over the error message, we can see + For now, however, we must make some kind of progress. + If we step back and gloss over the error message, we can see hunk ./en/ch02-starting.xml 495 - it. + it. It will come. + + The numerous error messages have a purpose: they actually + help us to write correct code, by making us perform some + amount of debugging up front, before we ever + run a program. If you are coming from a background of working + with more permissive languages, this way of working may come + as something of a shock. Bear with us. hunk ./en/ch02-starting.xml 507 - - Text, strings and lists - - If you are familiar with a language like Python, you'll find - Haskell's notations for strings and lists - familiar. - - A text string is surrounded by double quotes. + + Lists hunk ./en/ch02-starting.xml 510 - &basics.ghci:string; - - As in many languages, we can represent hard-to-print - characters by escaping them. Haskell's escape - characters and escaping rules expand on the conventions - established by the C language (for details, see - ). + A list is surrounded by square brackets; the + elements are separated by commas. hunk ./en/ch02-starting.xml 513 - &basics.ghci:newline; + &basics.ghci:list; hunk ./en/ch02-starting.xml 515 - A list is surrounded by square brackets, with elements - separated by commas. + + Commas are separators, not terminators hunk ./en/ch02-starting.xml 518 - &basics.ghci:list; + Some languages permit the last element in a list to be + followed by an optional trailing comma before a closing + bracket, but Haskell doesn't allow this. If you leave in a + trailing comma, you'll get a parse error. + hunk ./en/ch02-starting.xml 524 - A list can be of any length. + A list can be of any length. The empty list is + written []. hunk ./en/ch02-starting.xml 529 - All elements of a list must have the same type. + All elements of a list must be of the same type. hunk ./en/ch02-starting.xml 533 - Once again, &ghci;'s error message is verbose, but it's - simply telling us that it can't figure out how to turn the - string into a number, so the list expression isn't properly - typed. (It chose to try to turn the string into a number because - the list starts with a number.) - + Once again, &ghci;'s error message is verbose, but + it's simply telling us that there is no way to turn the string + into a number, so the list expression isn't properly typed. + hunk ./en/ch02-starting.xml 543 - Notice that range notation gives us a closed - interval; the list contains both endpoints. + Here, the .. characters denote a + range. We can only use range notation for types we can count. + Range notation makes no sense for rational numbers, for example, + because there is not a countable number of rationals. + + By the way, notice that the above use of range + notation gives us a closed interval; the + list contains both endpoints. hunk ./en/ch02-starting.xml 559 - In the latter case above, the list is quite sensibly missing - the end point of the range, because it isn't an element of the - series we defined. + In the latter case above, the list is quite + sensibly missing the end point of the range, because it isn't an + element of the series we defined. + + We can omit the end point of a range. If the type of the + range 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. hunk ./en/ch02-starting.xml 568 + + Beware ranges of floating point numbers + + Here's a non-intuitive bit of behaviour. + + &basics.ghci:range.double; + + 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. + + 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. + + + + Operators on lists + + There are two ubiquitous operators for working with + lists. We concatenate two lists using the + (++) operator. + + &basics.ghci:concat; + + More basic is the (:) operator, which + adds an element to the front of a list. This is pronounced + cons (short for + construct). + + &basics.ghci:concat; + + + + + + Strings and characters + + If you know a language like Perl or C, you'll find + Haskell's notations for strings familiar. + + A text string is surrounded by double quotes. + + &basics.ghci:string; + + 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, + '\n' denotes a newline character, and + '\t' is a tab character. For complete + details, see . + + &basics.ghci:newline; + hunk ./en/ch02-starting.xml 648 - Despite all our talk of types, our interactions with &ghci; - have so far been free of much type-related thinking. We haven't - told &ghci; what types we've been using, and it's mostly been - willing to accept our input. + While we've talked a little about types already, + our interactions with &ghci; have so far been free of much + type-related thinking. We haven't told &ghci; what types we've + been using, and it's mostly been willing to accept our + input. + + Haskell requires type names to start with an uppercase + letter, and variable names must start with a lowercase letter. + Bear this in mind as you read on; it makes it much easier to + read everything. hunk ./en/ch02-starting.xml 659 - The first thing we can do to start explicitly exploring the + The first thing we can do to start exploring the hunk ./en/ch02-starting.xml 672 - down the meaning of the last line of &ghci; output, then. + down the meaning of the last line of &ghci; output. hunk ./en/ch02-starting.xml 680 - We can read the text :: as meaning - the value on the left has the type on the - right. + We can read text of the form x :: + y as meaning the expression x + has the type y. hunk ./en/ch02-starting.xml 685 - And the value on the right is the type in question, - namely [Char]. + Here, the expression it has the + type [Char]. hunk ./en/ch02-starting.xml 690 - + hunk ./en/ch02-starting.xml 699 - When evaluating an expression, &ghci; won't change the - value of it until after it's finished. An - error in the evaluation will leave it - untouched, so we can type possibly bogus expressions with a - bit of a safety net. + When evaluating an expression, &ghci; won't + 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. hunk ./en/ch02-starting.xml 708 - Coupling it with liberal use of the + Couple it with liberal use of the hunk ./en/ch02-starting.xml 714 - + hunk ./en/ch02-starting.xml 721 - Haskell's arbitrary-precision - integer type is named Integer . - - - Type names start with an uppercase letter - - Both of the type names we've seen so far, - Char and Integer, have started with - capital letters. This isn't an accident; Haskell requires - type names to start with an uppercase letter, and variable - names must start with a lowercase letter. As far as Haskell - is concerned, a function is just another variable, so a - function name must start with a lowercase letter, too. - + Haskell's unbounded integral type is named + Integer . hunk ./en/ch02-starting.xml 731 - Ratio of Integer; we + Ratio of Integer. We hunk ./en/ch02-starting.xml 735 - the numerator and denominator are of different types, &ghci; - complains. + the numerator and denominator are of different types, or of the + same non-integral type, &ghci; complains. hunk ./en/ch02-starting.xml 740 - Although it's initially useful to have :set - +t giving us type information for every expression - we enter, this is a facility we'll quickly outgrow, simply - because it will become redundant. After a while, we'll often - know what type we expect an expression to have, so why get - &ghci; to remind us? We can turn off the extra type information + Although it's initially useful to have + :set +t giving us type information for + every expression we enter, this is a facility we'll quickly + outgrow: after a while, we'll often know what type we expect an + expression to have. We can turn off the extra type information hunk ./examples/ch02/basics.ghci 132 +--# concat + +"foo" ++ "bar" +[] ++ [1,2,3] ++ [4] + +--# cons + +1 : [2,3] +1 : [] + hunk ./examples/ch02/basics.ghci 149 -print "Here's a newline -->\n<-- See?" +putStr "Here's a newline -->\n<-- See?" hunk ./examples/ch02/basics.ghci 187 +--# range.double + +[1.0..1.8] + hunk ./examples/ch02/types.ghci 11 +"foo" hunk ./examples/ch02/types.ghci 32 +1.2 % 3.4 hunk ./examples/ch02/types.ghci 41 -:type 22 % 7 +:type 'a' }