Ben's Quick Summary of Haskell * Mathematics: Basic functions: + - / * Not equals is written as "/=" Negative numbers *require* parens: (-3) * Logic: Boolean: True, False and, or, not: &&, ||, not ==, <=, >=, <, > * Invoking a Function: functionname arg1 arg2 ... * More Math: Exponentiation of integer b: a ^ b Exponentiation of rational b: a ** b Ratio of a to b: a % b sqrt 16 round 3.4 ceiling 3.9 floor 3.2 succ 8 pred 5 --> non-boolean types are *never* understood as 'True' or 'False'. Operator precedence as usual. To see precedence and left/right infix, try ":info (func)" * Lists - use square brackets - all elements must be of SAME TYPE - can be of variable (or unbounded!) length - type of list is "[TYPE]" [2, 34, 90] ["hi", "boo", "moo", "cow"] [] Enumeration notation: [1..33] generates whole list, assuming the type is inherently enumerable. If we provide first 2 elements, 'step' is inferred: [1, 3..21] INFINITE lists are made when no endpoint is used: [1,2..] Appending two lists: use '++' operator: [8,2,7] ++ [9,9,1] creates [8,2,7,9,9,1] Consing (prepending) to a list: use ':' operatior 5:[8,2,7] creates [5,8,2,7] car and cdr via 'head' and 'tail' functions: head [2, 3, 1] == 2 tail [2, 3, 1] == [3, 1] last [2, 3, 1] == 1 take 2 ['a', 'b', 'c', 'd'] == ['a', 'b'] * Tuples - use parens - can have elements of different types - must be FIXED in length - type of tuple is "(type1, type2, etc.)" a 3-tuple: (3, "hello", True) a pair: ('c', 29.5) etc. () is the special "unit" type, a tuple of 0 elements. Just for pairs: fst ('a', 3) == 'a' snd ('a', 3) == 3 * Strings/Chars string type in double quotes: "string" char type in single quotes: 's' ** a string type is actually a LIST of chars! "" == [] "cat" == ['c','a','t'] standard escaping: \n, \t, etc. > putStrLn "print a string" "print a string" > 'c':"moo" "cmoo" > "ohai" ++ "there" "ohaithere" * ghci shortcuts --> GNU readline --> "it" is the last expression evaluated: > 2 + 2 4 > it ++ 3 7 --> load a Foo module as ":module +Foo" or ":m +Foo" --> see the type of xxx: ":type xxx" --> see types automatically: ":set +t" = ":unset +t" * It's Oh So Strongly Typed! -- variables always start with lowercase letter -- types always start with uppercase letter Basic types in play: Char [Char] Integer Double Ratio Integer * Code purity means that variable assignments are PERMANENT: x = 3 ... x cannot be reassigned to! its value is forever! Within ghci, use 'let': let x = 3 * Defining custom types (Algebraic Data Types) - a type with an Int and a String field: (POSITIONS MATTER) data MyType = MakeMyType Int String deriving (Show, Eq) MyType is "type constructor" MakeMyType is "value constructor". Often same-named as type constructor. - instantiating an object: myfoo = MakeMyType 13 "hello" - type synonyms (like C typedefs): type Blah = Int type Bloo = String type Blort = MyType - multiple possible constructor values: data MyType = MakeType1 Int String | MakeType2 [Int] | MakeType3 String deriving (Show) - can simulate a C enumerated type too: data Color = Blue | Yellow | Green deriving (Show) * Pattern Matching We can define a function as a *series* of equations. Haskell attempts to match our input to the first matching equation. sumList (x:xs) = x + sumList xs sumList [] = 0 COMMON LIST PATTERN is (x:xs), which calls out the car and cdr explicitly. Order of equations matters, since it determines the order of attempted pattern matching! myAge (MakeMyType age name) = age myName (MakeMyType age name) = name Wildcard is '_', which matches anything: myAge (MakeMyType age _) = age myName (MakeMyType _ name) = name When writing patterns, remember to make sure ALL possible patterns are defined! Wildcard can help with this, to define a 'default' value for unspecified patterns. Remember that pattrn-matching is about matching the SHAPE of the data, not the VALUES of data. (For that, see 'guards' later on.) * Record Syntax Long way to define accessor functions: myAge (MakeMyType age _) = age myName (MakeMyType _ name) = name Shorthand way of defining accessor functions: data MyType = MakeMyType { myAge :: Int, myName :: String } deriving (Show) Lets us instantiate more verbosely too, so to let us define fields in any order: foo = MakeMyType { myName = "Joe", myAge = 13} * Parameterized Types -- just like templates in other languages data MyType a = a : a deriving (Show) a is *any* type at all. Recursion is also the norm, i.e. data Tree a = Node a (Tree a) (Tree a) | Empty deriving (Show) * Awkward error reporting: error :: String -> a (returns 'anything' so it can be used from anywhere) error "something failed" * Local variables: Use either a 'let...in' block before the code, or a 'where' block after the code. foo x = let a = 3 - x b = 5 + x in if x > 0 then a * x else b * x or foo x = if x > 0 then a * x else b * x where a = 3 - x b = 5 + x Remember: local variables are bound to EXPRESSIONS, not values! Evaluation is lazy! Be careful of scoping. It's legal to have nested 'let' blocks which overshadow each other... the inner vals shadow the outer ones. Even parameter names can be shadowed by local variables. Optional: instead of whitespace defining blocks, one can use C-style curly braces and semicolons: foo x = let { a = 3 - x; b = 5 + x} in ... * Case case EXPRESSION of PATTERN1 -> EXPR1 PATTERN2 -> EXPR2 _ -> DEFAULT_EXPR ** don't be snagged by the desire to put variables in the patterns! Pattern-matching only tests the *shape* of the input, not the values. * Guards on patterns PATTERN | boolEXPR1 = body1 | boolEXPR2 = body2 ... If the pattern matches, each guard is evaluated in order. The first guard to be 'true' wins. Used within a case: case EXPRESSION of PATTERN1 | boolEXPR1 -> body1 | boolEXPR2 -> body2 PATTERN2 | boolEXPR3 -> body3 | boolEXPR4 -> body4 | otherwise -> defaultbody (Note that "otherwise = True" ... it's just there for readability). The simplest example of this is with a function definition (which is based on pattern-matching mechanics): myMax a b | a >= b = a | a < b = b