Haskell Fundamentals
Haskell Fundamentals
Prof. Susan Older
19 January 2017
(CIS 252) Haskell Fundamentals 19 January 2017 1 / 20
Haskell Programs
We’re covering material from Chapters 1-2 (and maybe 3) of the textbook.
A Haskell program is a series of comments and definitions.
Each comment begins with — (or appears between {− and −}) and
serves as documentation.
Each definition contains a type declaration and one or more
equations:
name :: t1 -> t2 -> · · · -> tn -> t
name x1 x2 · · · xn = exp
Each ti is a type, each xi is a formal parameter.
The type declaration serves as a contract:
What the function expects as input (xi has type ti )
What the function will deliver (exp has type t)
(CIS 252) Haskell Fundamentals 19 January 2017 2 / 20
What are Types?
Type = Collection of “similar” data values
Types are very important in Haskell:
Every expression has a type.
Types govern what/how we can combine.
Nothing gets evaluated unless the types make sense.
Consider the following function:
isPositive :: Int -> Bool
isPositive num = (num > 0)
isPositive expects an Int as input.
isPositive returns a Bool as a result.
(CIS 252) Haskell Fundamentals 19 January 2017 3 / 20
Some Very Basic Types
Haskell has lots of built-in types, including:
Bool
Boolean values: True and False
Int
Integer values from -2147483648 to 2147483647 (i.e., 32-bit integers)
Integer
All integers: full-precision integers
Float
Floating-point numbers, such as 3.267 or -81.09 or 12345.0
We’ll discuss these (and other types) in more detail later.
(CIS 252) Haskell Fundamentals 19 January 2017 4 / 20
Types: Simple Examples
thrice :: Int -> Int
thrice n = 3*n
isPositive :: Int -> Bool
isPositive num = (num > 0)
mystery :: Int -> Int -> Int
mystery x y = (thrice x) + y
What are the types of these expressions?
1 thrice 12 :: Int
2 thrice False …Type error
3 isPositive (thrice 12) :: Bool
4 mystery (thrice 12) 5 :: Int
(CIS 252) Haskell Fundamentals 19 January 2017 5 / 20
Terminology: Formal Parameters and Actual Parameters
Consider the following function:
simple :: Int -> Int -> Int
simple a b = a + 3*b
In the definition above, a and b are the formal parameters of simple.
They are names that appear in the function definition to represent the
input that may be passed into the function.
Suppose we evaluate simple (4+2) 5:
(4+2) and 5 are the actual parameters (a.k.a. arguments) of simple.
They are the expressions that appear in a function call/invocation.
(CIS 252) Haskell Fundamentals 19 January 2017 6 / 20
Evaluating Expressions in Haskell
Idea: Based on rewriting equations (just like in algebra!)
Happens after types are checked: type errors mean no evaluation
Lazy evaluation: expressions evaluated only when values needed
thrice (5+2) 3 * (5+2) 3 * 7 21
isPositive (mystery (2-3) 1) (mystery (2-3) 1) > 0
( (thrice (2-3)) + 1) > 0
( (3 * (2-3)) + 1) > 0
( (3 * -1) + 1) > 0
(-3 + 1) > 0
(-2) > 0
False
(CIS 252) Haskell Fundamentals 19 January 2017 7 / 20
What Are the Rules for Identifiers (i.e., Names)?
Identifiers begin with a letter, and can then be followed by any
combination of letters, digits, underscores ( ), and single quotes (’):
x Number a123 xy alpha’’’
Two important rules
1 Names of functions and variables must begin with a lowercase letter.
2 Names of types, type classes, constructors, and module names must
begin with an uppercase letter.
Convention: When names are built from multiple words, the second and
subsequent words are capitalized.
milesToKm, weightPerUnit
(CIS 252) Haskell Fundamentals 19 January 2017 8 / 20
Another Gotcha: Layout (Indentation Matters!)
Layout determines where definitions start and stop.
The Rule:
A definition ends at the first piece of text that lies at the same
indentation as (or to the left of) the start at that definition.
Guidelines:
For top-level definitions, start at the leftmost column.
When writing definitions, use the same indentation for each.
(Emacs can help you with this task.)
(CIS 252) Haskell Fundamentals 19 January 2017 9 / 20
More about Bool
Exactly two values: True, False
Standard operators:
(&&) :: Bool -> Bool -> Bool (==) :: Bool -> Bool -> Bool
(||) :: Bool -> Bool -> Bool (/=) :: Bool -> Bool -> Bool
not :: Bool -> Bool
e1 && e2: evaluates to True when both e1 and e2 evaluate to True
(evaluates to False when either e1 or e2 evaluates to False)
e1 || e2: evaluates to True when either e1 or e2 evaluates to True
(evaluates to False when both e1 and e2 evaluate to False)
not e: evaluates to True when e evaluates to False (and vice versa)
== and /= are equality and inequality (respectively)
(CIS 252) Haskell Fundamentals 19 January 2017 10 / 20
Integers: Int and Integer
Int: integers from -2147483648 to 2147483647 (i.e., 32-bit integers)
Integer: all integers (i.e., full-precision integers)
Standard operators and functions (also work for Integer)
(+), (*), (-), div, mod, (^) :: Int -> Int -> Int
even, odd :: Int -> Bool
(==), (/=) :: Int -> Int -> Bool
(<), (<=), (>), (>=) :: Int -> Int -> Bool
You cannot add (or multiply or …) an Int with an Integer.
However, you can convert between Int and Integer:
toInteger:: Int -> Integer fromInteger:: Integer -> Int
(CIS 252) Haskell Fundamentals 19 January 2017 11 / 20
Floating-point Numbers: Float
Float: single-precision floating-point numbers
Examples include: 543.874 -346.2 12.0
Some standard operators and functions
(+), (*), (-), /, (**) :: Float -> Float -> Float
(==), (/=) :: Float -> Float -> Bool
(<), (<=), (>), (>=) :: Float -> Float -> Bool
ceiling, floor, round :: Float -> Integer
More functions listed in Figure 3.2 of the textbook (page 58).
(CIS 252) Haskell Fundamentals 19 January 2017 12 / 20
Let’s Write Some Functions!
As time permits, let’s write these functions:
average :: Float -> Float -> Float
Accepts two numbers and calculates their average
allPositive :: Int -> Int -> Int -> Bool
Accepts three integers and determines whether they’re all positive
someNegative :: Int -> Int -> Int -> Bool
Accepts three integers and determines whether at least one is negative
(CIS 252) Haskell Fundamentals 19 January 2017 13 / 20
Dealing with Cases: What to Do?
According to SU’s Bursar, tuition for main campus undergrads is:
Per semester (12-19 credits) $21,720
Per credit (first 11) 1,891
Per credit (20 or more) 1,305
Let’s write a Haskell function that:
Accepts as input the number of credits being taken
Calculates the tuition cost of that number of credits
(CIS 252) Haskell Fundamentals 19 January 2017 14 / 20
Conditional Equations
Let’s look at one solution:
tuition :: Int -> Int
tuition cr
| cr <= 0 = 0 | cr <= 11 = cr * 1891 | cr >= 20 = cr * 1305
| otherwise = 21720
1 There are four guards (all of which must have type Bool) :
cr <= 0 cr <= 11 cr >= 20 otherwise
2 There are four possible results (all of which must have type Int):
0 cr * 1891 cr * 1305 21720
3 Evaluation rule: Return the result associated with the first guard that
evaluates to True (Note: otherwise always evaluates to True.)
(CIS 252) Haskell Fundamentals 19 January 2017 15 / 20
Conditional Equations: A Quick Quiz
Consider the following:
contrived :: Int -> Int -> Int
contrived m n
| even m && m > n = n*2 — && is and
| odd n || n<3 = m -- || is or | otherwise = m+n+1 What are of the values of the following expressions? contrived 100 7 14 contrived 16 100 117 contrived 321 7 321 contrived 44 0 0 contrived 95 0 95 contrived 28 15.0 Type Error! (CIS 252) Haskell Fundamentals 19 January 2017 16 / 20 http://bursar.syr.edu/wp-content/uploads/2016/06/2016-2017-Tuition-and-fees-booklet.pdf Quick Side Discussion #1: Overloading We’ve seen that == and + have the following types (among others): (==):: Bool -> Bool -> Bool
(==):: Int -> Int -> Bool
(==):: Integer -> Integer -> Bool
(==):: Float -> Float -> Bool
(+):: Int -> Int -> Int
(+):: Integer -> Integer -> Integer
(+):: Float -> Float -> Float
These are instances of overloading:
The same name (or symbol) is used to represent different
operations/functions on different types.
Haskell determines from context which definition is needed.
Overloading is handled through type classes (more on that later).
(CIS 252) Haskell Fundamentals 19 January 2017 17 / 20
More Types: Char
Sample values: ’a’, ’A’, ’3’, ’ ’, ’\n’ (newline), ’\t’ (tab)
The module Data.Char contains lots of useful functions, including:
isDigit :: Char -> Bool isControl :: Char -> Bool
isAlpha :: Char -> Bool toUpper :: Char -> Char
isAlphaNum :: Char -> Bool toLower :: Char -> Char
isUpper :: Char -> Bool ord :: Char -> Int
isLower :: Char -> Bool chr :: Int -> Char
To use these functions, include the following at the top of your
Haskell file:
import Data.Char
(CIS 252) Haskell Fundamentals 19 January 2017 18 / 20
More Types: String
Strings are sequences of characters, enclosed with double quotes:
“hello!”
“1234”
“” (empty string)
“abc\ndefg\nh\ti”
String concatenation:
(++) :: String -> String -> String
Example: “abc” ++ “1234” evaluates to “abc1234”
Later we’ll see:
String = [Char] (i.e., strings are lists of characters)
(CIS 252) Haskell Fundamentals 19 January 2017 19 / 20
Quick Side Discussion #2: Functions versus Operators
When calling a function:
The function name appears before its arguments:
div 17 4
tuition 16
contrived 100 7
When using operators (which always have two arguments):
Operators appear between their two arguments:
6 * (3+4)
“abc” ++ “123xy”
If you want to treat operators like functions, put them in parentheses:
(*) 6 (3+4) (*) 6 ((+) 3 4)
(++) “abc” “123xy”
(CIS 252) Haskell Fundamentals 19 January 2017 20 / 20