Thinking Functionally with Haskell

Thinking Functionally with Haskell by Richard Bird Read Free Book Online

Book: Thinking Functionally with Haskell by Richard Bird Read Free Book Online
Authors: Richard Bird
(-b+r)/e)
    where {disc = b*b - 4*a*c; r = sqrt d; e = 2*a}
    Here the where clause uses explicit braces and semicolons rather than appealing to Haskell’s layout rules. Instead, we could have written
    where disc = b*b - 4*a*c
    r = sqrt d
    e = 2*a
    But we couldn’t have written
    where disc = b*b - 4*a*c
    r = sqrt d
    e = 2*a
    The layout (or offside ) rule takes effect whenever the opening brace is omitted after the keyword where or do (and also after let ). When this happens the indentation of the next item, whether or not on a new line, is remembered. For each subsequent line, if it is indented more, then the previous line is continued; if it is indented the same amount, then a new item begins; and if it is indented less, then the layout list is ended. At least, that’s roughly the offside rule.
    The offside rule explains why there is an indentation in the declarations of type classes and instances:
    class Foo a where
    I am part of the class declaration.
    So am I.
    Now the class declaration has ended.
    You can always put in braces and semicolons if in any doubt. Actually the offside rule can still cause confusion when used with do -notation. So the recommendation is belts, braces and semicolons.
    And you thought the football offside rule was complicated.
2.8 Exercises
    Exercise A
    On the subject of precedence, this question comes from Chris Maslanka’s puzzle page in the Guardian newspaper: ‘Is a half of two plus two equal to two or three?’
    Exercise B
    Some of the following expressions are not syntactically correct, while others are syntactically correct but do not have sensible types. Some are wellformed. Which is which? In the case of a wellformed expression, give a suitable type. Assume double :: Int -> Int . I suggest you don’t use a computer to check your answers, but if you do, be prepared for some strange error messages.
    The expressions are:
    [0,1)
    double -3
    double (-3)
    double double 0
    if 1==0 then 2==1
    "++" == "+" ++ "+"
    [(+),(-)]
    [[],[[]],[[[]]]]
    concat ["tea","for",'2']
    concat ["tea","for","2"]
    Exercise C
    In the good old days, one could write papers with titles such as
    ‘The morphology of prex – an essay in meta-algorithmics’
    These days, journals seem to want all words capitalised:
    ‘The Morphology Of Prex – An Essay In Meta-algorithmics’
    Write a function modernise :: String -> String which ensures that paper titles are capitalised as above. Here are some helpful questions to answer first: 1. The function toLower :: Char -> Char converts a letter to lowercase. What do you think is the name of the prelude function that converts a letter to uppercase?
    2. The function words :: String -> [Word] was used in the previous chapter. What do you think the prelude function unwords :: [Word] -> String
    does? Hint: which, if either, of the following equations should hold?
    words . unwords = id
    unwords . words = id
    3. The function head :: [a] -> a returns the head of a nonempty list, and tail :: [a] -> [a] returns the list that remains when the head is removed. Suppose a list has head x and tail xs . How would you reconstruct the list?
    Exercise D
    Beaver is an eager evaluator, while Susan is a lazy one. 1 How many times would Beaver evaluate f in computing head (map f xs) when xs is a list of length n ? How many times would Susan? What alternative to head . map f would Beaver prefer?
    The function filter p filters a list, retaining only those elements that satisfy the boolean test p . The type of filter is filter :: (a -> Bool) -> [a] -> [a]
    Susan would happily use head . filter p for a function that finds the first element of a list satisfying p . Why would Beaver not use the same expression?
    Instead, Beaver would probably define something like
    first :: (a -> Bool) -> [a] -> a
    first p xs | null xs = error "Empty list"
    | p x = ...
    | otherwise = ...
    where x = head xs
    The function null returns True on an empty list, and False otherwise. When evaluated, the expression error message stops

Similar Books

Prescribed for Love

Mallory Moutinho

#5 Not What I Expected

Laurie Friedman

Becoming Death

Melissa Brown

Screening Room

Alan Lightman