What’s Haskell?
- Haskell is a purely functional programming language.
- In purely functional programming you don’t tell the computer what to do as such but rather you tell it what stuff is.
- Haskell is lazy.
- If you say that a is 5, you can’t say it’s something else later because you just said it was 5.
- a function has no side-effects. The only thing a function can do is calculate something and return it as a result.
xs = [1,2,3,4,5,6,7,8]
doubleMe(doubleMe(doubleMe(xs)))
- Haskell is statically typed.
- Haskell is elegant and concise.
Functional programming is a style of programming in which expressions are more important than using statements.
Start out
- Simple arithmetic
- Boolean algebra
- Function application has the highest precedence
- spaces are used for function application
In imperative languages you can just skip a couple of steps if the condition isn’t satisfied but in Haskell every expression and function must return something.
We usually use '
to either denote a strict version of a function (one that isn’t lazy) or a slightly modified version of a function or a variable.
conanO'Brien = "It's a-me, Conan O'Brien!"
- functions can’t begin with uppercase letters.
- this function doesn’t take any parameters.
Lists are a homogenous data structure.
Lists can be compared if the stuff they contain can be compared in lexicographical order.
head, tail, last, init
length, null, reverse
take, drop, maximum, minimum
sum, product, elem
ranges
cycle, repeat, replicate
Types
A type is a name for a collection of related values.
Applying a function to one or more arguments of the wrong type is called a type error.
All type errors are found at compile time.
Basic Types
Bool, Char, String, Int, Integer, Float
List Types
A list is sequence of values of the same type.
Tuple Types
A tuple is a sequence of values of different types:
Function Types
A function is a mapping from values of one type to
values of another type.
Curried Functions
Functions with multiple arguments are also possible by returning functions as results.
add :: (Int,Int) → Int
add’ :: Int → (Int → Int)
Functions that take their arguments one at a time are called curried functions, celebrating the work of Haskell Curry on such functions.
Polymorphic Functions
A function is called polymorphic (“of many forms”) if its type contains one or more type variables.
Overloaded Functions
A polymorphic function is called overloaded if its type contains one or more class constraints.
Haskell has a number of type classes:
Num
, Eq
, Ord
Defining Functions
Conditional Expressions
signum :: Int → Int
signum n = if n < 0 then -1 else
if n == 0 then 0 else 1
Guarded Equations
signum n | n < 0 = -1
| n==0 = 0
| otherwise = 1
Pattern Matching
True && b = b
False && _ = False
List Patterns
Lambda Expressions
Functions can be constructed without naming the functions by using lambda expressions.
Operator Sections
(1+)
- successor function(1/)
- reciprocation function(*2)
- doubling function(/2)
- halving function
Recursive Functions
Interactive Programs
- batch programs
- interactive programs
Haskell programs have no side effects.
Interactive programs have side effects.
Interactive programs can be written in Haskell by using types to distinguish pure expressions from impure actions that may involve side effects.
IO Char
: The type of actions that return a character.
IO ()
: The type of purely side effecting actions that return no result value.
Note: () is the type of tuples with no components.
Basic Actions
getChar
: reads a character from the keyboard, echoes it to the screen, and returns the character as its result value
getChar :: IO Char
putChar
: writes the character c to the screen, and returns no result value
putChar :: Char → IO ()
return v
: simply returns the value v, without performing any interaction
return :: a → IO
Sequencing
act :: IO (Char,Char)
act = do x ← getChar
getChar
y ← getChar
return (x,y)
Derived Primitives
getLine :: IO String
getLine = do x ← getChar
if x == '\n' then
return []
else
do xs ← getLine
return (x:xs)
putStr :: String → IO ()
putStr [] = return ()
putStr (x:xs) = do putChar x
putStr xs
putStrLn :: String → IO ()
putStrLn xs = do putStr xs
putChar '\n'
strlen :: IO ()
strlen = do putStr "Enter a string: "
xs ← getLine
putStr "The string has " putStr (show (length xs)) putStrLn " characters"
Hangman
- One player secretly types in a word.
- The other player tries to deduce the word, by entering a sequence of guesses.
- For each guess, the computer indicates which letters in the secret word occur in the guess.
- The game ends when the guess is correct.
Top down:
import System.IO
hangman :: IO ()
hangman = do putStrLn "Think of a word:"
word <- sgetLine
putStrLn "Try to guess it:"
play word
sgetLine :: IO String
sgetLine = do x <- getCh
if x == '\n' then
do putChar x
return []
else
do putChar '-'
xs <- sgetLine
return (x:xs)
getCh :: IO Char
getCh = do hSetEcho stdin False
x <- getChar
hSetEcho stdin True
return x
play :: String -> IO ()
play word = do putStr "? "
guess <- getLine
if guess == word then
putStrLn "You got it!!"
else
do putStrLn (match word guess)
play word
match :: String -> String -> String
match xs ys = [if elem x ys then x else '-' | x <- xs]