A Haskell A Day: Quick Start
The following is a short example of Haskell code, which gives a quick overview of the language.
(
http://www.haskell.org/hawiki/HaskellDemo
(BSD licensed))
Comments and Variables
{- comments are enclosed between braces with a dash, like this paragraph. -} -- alternatively, comment starts with two dashes and ends at the end of line. -- assign a variable somenumber = 1 -- assign a string somestring = "somestring" -- a item's type can be declared explicitly: stringtwo :: String stringtwo = "another string" {- all data in Haskell has a type. Almost always, the type declaration can be omitted, because Haskell can figure it out for you. -}
Defining a Function
{- declare the function's type. This means, add1 is a function, which takes one argument of type Integer and returns a data of type Integer -} add1 :: Integer -> Integer -- This defines the body of add1: add1 x = x + 1 -- example of using the function. -- this adds one to 41 to get the answer fortytwo = add1 41 {- anonymous function. Note that \x indicates parameter, and “->” is used instead of the equal sign = -} \x -> x + 2 -- apply a anonymous function to a expression @eval (\x -> x + 2) 1 -- anonymous function can be assigned to variable add2 = (\x -> x + 2) -- this is equivalent as the definition “add2 x = x + 2” -- defining function with two parameters f :: Integer -> Integer -> Integer f x y = x + y {- Note the type declaration. The infix operator “->” has a higher precedence with the right side. That is, “a -> b -> c” means “a -> (b -> c)”, so “Integer -> Integer -> Integer” means “Integer -> (Integer -> Integer)”. The type “a -> (b -> c)” practically means a function taking type a and returns a function with type (b -> c). In our case, “f” is a function that takes a Integer x and returns a function of type Integer -> Integer, and this function is given y as argument. The function of two parameters f(x,y) can be thought of as made of two other functions of single parameter g(x) and h(x). For each particular value a, g(a) returns a particular function h, such that h(b) == f(a,b). That is, f(a,b) == g(a)(b). This is why its type declaration is like a sequence. -} {- this two-step nature also means that you can give one argument to f and get a intermediate function h. This is called partial application of a function. For example, we define a function addOne using our f(x,y). -} addOne :: Integer -> Integer addOne = f 1
Data Types
-- datatype data Temp = Cold | Hot data Season = Winter | Spring | Summer | Fall deriving Show -- 'Show' is how you turn a value into a string for display -- 'show Winter' will work in Hugs -- 'show Hot' will give an error because we didn't give a way to turn -- Cold and Hot values into a string. mySeason :: Season mySeason = Summer -- type aliases type Name = String type Age = Integer -- more complex types data People = Person Name Age -- example author1 = Person "Shae Erisson" 33 author2 = Person "Cale Gibbard" 21 author3 = Person "Amir Livne Bar-On" 18 birthday (Person name age) = Person name (age + 1) -- records data Tuple = {person :: Person, favoriteSeason :: Season} -- example database = [Tuple {person = author1, favoriteSeason = Summer}, Tuple {person = author3, favoriteSeason = Fall}] -- person (head database) is author1 -- favoriteSeason (database !! 1) is Fall -- polymorphic (parameterized, recursive) datatype data Tree a = Nil | Node (Tree a) a (Tree a) deriving Show myTree :: Tree Int myTree = Node Nil 1 Nil myOtherTree :: Tree Season myOtherTree = Node Nil Winter (Node Nil Summer Nil) -- pattern matching -- each time the function is called, each line is tried in turn, -- the first matching left hand side gets to execute its right hand side mylength [] = 0 mylength (x:xs) = 1 + mylength xs -- the second line with the (x:xs) construct above means that if a list is passed to the function -- the first item of the list is assigned to x, and the rest of the list is assigned to xs -- you can try the mylength function above by typing this into hugs or ghci: -- mylength [1,2,3] -- more pattern matching -- the underscore matches anything at all, but doesn't assign to anything weather :: Season -> Temp weather Summer = Hot weather _ = Cold -- where clauses introduce definitions local to a function. ackermann :: Integer -> Integer ackermann n = ack n n -- (Peter's variant of the Ackermann function) where ack 0 m = m+1 ack n 0 = ack (n-1) 1 ack n m = ack (n-1) (ack n (m-1)) -- Typeclasses let you define the same operations on different types -- the operators equal to ( == ) and not equal to ( /= ) are in the typeclass Eq instance Eq Temp where Cold == Cold = True Hot == Hot = True _ == _ = False -- Eq is a built-in typeclass for checking equality, let's define our own typeclass -- this isn't a very useful typeclass, because it can't sensibly be defined for anything other than Char -- (because vowels are only in the alphabet, there aren't vowels in numbers) -- something like class XML would be more useful, and could be defined for every type class CharExts a where isVowel :: a -> Bool isConsonant :: a -> Bool instance CharExts Char where isVowel a = elem a "aeiouAEIOU" isConsonant a = elem a (filter (not . isVowel) ['A'..'Z'] ++ output left in - ['a'..'z']) -- short demonstration of guards -- each conditional expression is tried in turn guard x | x == 0 = 4 | (x*x) < 64 = 5 | otherwise = 6 -- guard 0 evaluates to 4 -- guard 1 evaluates to 5 -- guard 9 evaluates to 6 -- can you guess what guard -1 will be? -- Lazy computation example -- Evaluation will bounce back and forth between the two infinite lists computing each element. odds = 1 : map (+1) evens evens = map (+1) odds
2005-10