To understand craftsmanship, we must ask not only "What has been made?" and "How has this been made?" but also "Who made this and why?" Craftsmanship is a relationship between the maker and the process of creation. It is not simply a set of skills one acquires, like the ability to read or drive a car. More than anything, craftsmanship is a matter of attitude: why we choose to devote time to such a demanding endeavor, why we choose to make a certain object of a certain appearance, and how we go about it.> module Lec01 where > > import Prelude hiding ((.)) Let's get started. Here's a simple arithmetic function: > mean :: Int -> Int -> Int > mean x y = div (x + y) 2 We can make an ordinary function *infix* using backticks: > mean' :: Int -> Int -> Int > mean' x y = x + y `div` 2 Run `ghci` to test your program. Here are some more interesting, recursive functions: > fact :: Int -> Int > fact 0 = 1 > fact n = n * fact' (n - 1) There are conditionals: > fact' :: Int -> Int > fact' n = if n <= 0 > then 1 > else n * fact' (n - 1) Here's the pipe form for conditionals within a top-level pattern match: > factPat :: Int -> Int > factPat n | n <= 0 = 1 > factPat n = n * factPat (n - 1) The following code is redundant and poorly typeset. > fact'' :: Int -> Int > fact'' 0 = 1 > fact'' 1 = 1 > fact'' 2 = 2 > fact'' n = if n < 0 then 1 > else n * fact'' (n - 1) But don't get the wrong idea: you can have more than one base case, if you like. > fib :: Int -> Int > fib 0 = 1 > fib 1 = 1 > fib n = fib (n - 1) + fib (n - 2) Here's an "accumulator passing" function, using a `where` clause to nest a local definition. Can you see how `fibAux` is like a loop? > fib' :: Int -> Int > fib' n = fibAux 1 1 n > where fibAux f2 f1 0 = f2 > fibAux f2 f1 n = fibAux f1 (f1+f2) (n-1) To see how important type annotations are to getting good error messages, try removing the type annotation on `fibAux` and forgeting to apply `fibAux` in the third case. Here's our first datatype, representing the days of the week. > data Day = > Sunday > | Monday > | Tuesday > | Wednesday > | Thursday > | Friday > | Saturday > deriving Show Note the use of capital letters for the type itself (`Day`) and for its constructors (`Monday`, etc.). Try using these constructors in `ghci`. Here's simple function to determine whether or not it's party time; note how the wildcard pattern `_` doesn't bind any names and matches anything. > isWeekend :: Day -> Bool > isWeekend Saturday = True > isWeekend Sunday = True > isWeekend _ = False Top-level definitions in Haskell automatically do pattern matching, but we can be explicit if we like: > isWeekend' :: Day -> Bool > isWeekend' d = > case d of > Saturday -> True > Sunday -> True > _ -> False I think `isWeekend'`'s definition is slightly less good than `isWeekend`: why do an expression-level match when we could have matched at the top-level? Let's define `isWeekday` in terms of a function we already have: > isWeekday :: Day -> Bool > isWeekday d = not (isWeekend d) But we can also use the math-like composition operator: > isWeekday' :: Day -> Bool > isWeekday' = not . isWeekend Before you go on, try to guess `(.)`'s type. It's an ordinary function! > (.) :: (b -> c) -> (a -> b) -> (a -> c) > f . g = \x -> f (g x) Finally, note that booleans aren't builtins in Haskell. Somewhere in the Prelude (the standard definition), someone defined the booleans: ``` data Bool = False | True ``` And we could even define our own conditional: > myIf :: Bool -> a -> a -> a > myIf True t e = t > myIf False t e = e > > factMine :: Int -> Int > factMine n = myIf (n <= 0) 1 (n * fact (n - 1))---Peter Korn, *Woodworking Basics: Mastering the Essentials of Craftsmanship*