Prof. Susan Older

19 January 2017

(CIS 252) Haskell Fundamentals 19 January 2017 1 / 20

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.

(CIS 252) Haskell Fundamentals 19 January 2017 9 / 20

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

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’, ’ ’, ’
’ (newline), ’ ’ (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

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
defg
h i”

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