0% found this document useful (0 votes)
55 views

FP With Haskell: CS5205: Foundations in Programming Languages

Haskell is a pure, lazy functional programming language that uses expressions instead of statements. It has built-in types like integers, characters, and lists, as well as user-defined algebraic data types. Haskell supports polymorphic types through type classes that allow for overloading of functions. Types are strictly checked and Haskell avoids side effects through a purely functional approach.

Uploaded by

yashbhardwaj
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views

FP With Haskell: CS5205: Foundations in Programming Languages

Haskell is a pure, lazy functional programming language that uses expressions instead of statements. It has built-in types like integers, characters, and lists, as well as user-defined algebraic data types. Haskell supports polymorphic types through type classes that allow for overloading of functions. Types are strictly checked and Haskell avoids side effects through a purely functional approach.

Uploaded by

yashbhardwaj
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 43

CS5205: Foundations in

Programming Languages
FP with Haskell

A pure lazy functional language that


embodies many innovative ideas
in language design.

CS5205 Haskell 1
Haskell

• Advanced programming language – reusable,


abstract, efficient, feature-rich.
• Functions and Expressions
• Values, Types and Lazy evaluation
• Products, Records and Algebraic Types
• Polymorphic Types & Type Classes
• Higher-Order Functions
• Infix operator and sections.

Reference --- A Gentle Introduction to Haskell 98


http://www.haskell.org/tutorial

CS5205 Haskell 2
Functions

• Function is a black box that converts input to


output. A basis of software component.

…. inputs …. inputs

function function global


vars

…. output …. output

pure impure
CS5205 Haskell 3
Example of Functions
• Double a given input.
square :: Int -> Int

square x = x*x

• Conversion from fahrenheit to celcius


fahr_to_celcius :: Float -> Float

fahr_to_celcius temp = (temp – 32)/1.8

• A function with multiple results - quotient & remainder


divide :: Int -> Int -> (Int,Int)

divide x y = (div x y, mod x y)

CS5205 Haskell 4
Expression-Oriented

• Instead of imperative commands/statements, the focus is


on expression.

• Instead of command/statement :
if e1 then stmt1 else stmt2

• We use conditional expressions :


if e1 then e2 else e3

CS5205 Haskell 5
Expression-Oriented

• An example function:
fact :: Integer -> Integer
fact n = if n=0 then 1
else n * fact (n-1)

• Can use pattern-matching instead of conditional


fact 0 = 1
fact n = n * fact (n-1)

• Alternatively:
fact n = case n of
0 -> 1
a -> a * fact (a-1)

CS5205 Haskell 6
Conditional  Case Construct
• Conditional;
if e1 then e2 else e3

• Can be translated to
case e1 of
True -> e2
False -> e3

• Case also works over data structures (without any extra


primitives)
length xs = case xs of
[] -> 0;
y:ys -> 1+(length ys)

Locally bound variables


CS5205 Haskell 7
Lexical Scoping
• Local variables can be created by let construct to give
nested scope for the name space. Example:
let y = a+b
f x = (x+y)/y
in f c + f d

• For scope bindings over guarded expressions, we


require a where construct instead:
f x y | x>z = …
| y==z = …
| y<z = ….
where z=x*x

CS5205 Haskell 8
Layout Rule
• Haskell uses two dimensional syntax that relies on
declarations being “lined-up columnwise”
let y = a+b
f x = (x+y)/y is being parsed as:
in f c + f d
let { y = a+b
; f x = (x+y)/y }
in f c + f d

• Rule : Next character after keywords where/let/of/do


determines the starting columns for declarations.
Starting after this point continues a declaration, while
starting before this point terminates a declaration.

CS5205 Haskell 9
Expression Evaluation
• Expression can be computed (or evaluated) so that it is
reduced to a value. This can be represented as:
e  ..  v

• We can abbreviate above as:


e * v

• A concrete example of this is:


inc (inc 3)  inc (4)  5

• Type preservation theorem says that:

if e :: t Æ e  v , it follows that v :: t

CS5205 Haskell 10
Values and Types
• As a purely functional language, all computations are
done via evaluating expressions (syntactic sugar) to
yield values (normal forms as answers).
• Each expression has a type which denotes the set of
possible outcomes.
• v :: t can be read as value v has type t.
• Examples of typings, associating a value with its
corresponding type are:
5 :: Integer
'a' :: Char
[1,2,3] :: [Integer]
('b', 4) :: (Char, Integer)
“cs5” :: String (same as [Char])

CS5205 Haskell 11
Built-In Types
• They are not special:
data Char = ‘a’ | ‘b’ | …
data Int = -65532 | … | -1 | 0 | 1 | …. | 65532
data Integer = … | -2 | -1 | 0 | 1 | 2 | …

• Tuples are also built-in.


data (a,b) = M2(a,b)
data (a,b,c) = M3(a,b,c)
data (a,b.c.d) = M4(a,b,c,d)

• List type uses an infix operator:


data [a] = [] | a : [a]

[1,2,3] is short hand for 1 : (2 : (3 : []))

CS5205 Haskell 12
User-Defined Algebraic Types
• Can describe enumerations:
data Bool = False | True
data Color = Red | Green | Blue | Violet

• Can also describe a tuple


data Pair = P2 Integer Integer
data Point a = Pt a a
type variable
• Pt is a data constructor with type a -> a -> Point a

Pt 2.0 3.1 :: Point Float


Pt ‘a’ ‘b’ :: Point Char
Pt True False :: Point Bool

CS5205 Haskell 13
Recursive Types
• Some types may be recursive:
data Tree a = Leaf a | Branch (Tree a) (Tree a)

• Two data constructors:


Leaf :: a -> Tree a
Branch :: Tree a -> Tree a -> Tree a

• An example function over recursive types:


fringe :: Tree a -> [a]

fringe (Leaf x) = [x]


fringe (Branch left right) = (fringe left) ++
(fringe right)

CS5205 Haskell 14
Polymorphic Types
• Support types that are universally quantified in some
way over all types.
• 8 c. [c] denotes a family of types, for every type c, the type
of lists of c.

• Covers [Integer], [Char], [Integer->Integer], etc.

• Polymorphism help support reusable code, e.g


length :: 8 a. [a] -> Integer
length [] = 0
length (x:xs) = 1 + length xs

CS5205 Haskell 15
Polymorphic Types
• This polymorphic function can be used on list of any type..
length [1,2,3] ) 2
length [‘a’, ’b’, ‘c’] ) 3
length [[1],[],[3]] ) 3

• More examples :
head :: [a] -> a
head (x:xs) = x

tail :: [a] -> [a]


tail (x:xs) = xs

• Note that head/tail are partial functions, while length is


a total function?
CS5205 Haskell 16
Principal Types
• Some types are more general than others:
[Char] <: 8 a. [a] <: 8 a. a

• An expression’s principal type is the least general type


that contains all instances of the expression.

• For example, the principal type of head function is


[a]->a, while [b] -> a, b -> a, a are correct but
too general but [Integer] -> Integer is too
specific.

• Principal type can help supports software reusability


with accurate type information.
CS5205 Haskell 17
Type Synonyms
• It is possible to provide new names for commonly used
types
type String = [Char]
type Person = (Name, Address)
type Name = String
data Address = None | Addr String

• Type synonyms do not define new types, but simply


give new names for existing types.
type AssocList a b = [(a,b)]

• Their use can improve code readability.

CS5205 Haskell 18
Type Classes and Overloading
• Parametric polymorphism works for all types. However,
ad-hoc polymorphism works for a class of types and can
systematically support overloading.
• For example, what is the type for (+) operator?
(+) :: a -> a -> a
(+) :: Int -> Int -> Int
(+) :: Float -> Float -> Float

• What about methods built from (+)?


double x = x+x

• Better solution is to use a type class for numerics!


(+) :: Num a => a -> a -> a
double :: Num a => a -> a
CS5205 Haskell 19
Equality Class
• Similar issue with equality. Though it looks like:
(==) :: a -> a -> Bool

• Equality can be tested for data structures but not


functions!

• Solution is to define a type class that supports the


equality method, as follows:
class Eq a where
(==),(/=) :: a -> a -> Bool
x /= y = not (x==y)
default definition
• Then: (==) :: Eq a => a -> a -> Bool

CS5205 Haskell 20
Members of Eq Type Class
• The class is open and can be extended, as follows:
instance Eq Integer where
x == y = x ‘integerEq’ y

instance Eq Float where


x == y = x ‘FloatEq’ y

• Recursive type can also be handled but elements may


need to be given type qualifiers.
instance (Eq a) => Eq (Tree a) where
Leaf a == Leaf b = a==b
(Branch l1 r1) == (Branch l2 r2)
= (l1==l2) && (r1==r2)
_ == _ = False

CS5205 Haskell 21
More Members of Eq Type Class
• Similarly, we may use structural equality for List:
instance (Eq a) => Eq ([a]) where
[] == [] = True
(x:xs) == (y:ys) = (x==y) && (xs==ys)
_ == _ = False

• One use of Eq class is:


elem :: (Eq a) => a -> [a] -> Bool
x ‘elem’ [] = False
x ‘elem’ (y:ys) = (x==y) || (x ‘elem’ ys)

• Exercise : define Set as an instance of the Eq class.

CS5205 Haskell 22
Numeric Class
• There is a hierarchy of numeric classes. Most basic is:
class Num a where
(+),(-),(*) :: a -> a -> a
negate,abs,signum :: a -> a
fromInteger :: Integer -> a

x – y = x + (negate y)
negate x = 0 – x

instance Num Int where



instance Num Integer where

instance Num Float where

instance Num Double where

CS5205 Haskell 23
Functions and its Type
• Method to increment its input
inc x = x+1

• Or through lambda expression (anonymous functions)


(\ x -> x+1)

• They can also be given suitable function typing:


inc :: Num a => a -> a
(\x -> x+1) :: Num a => a -> a

• Types can be user-supplied or inferred.

CS5205 Haskell 24
Functions and its Type
• Some examples
(\x -> x+1) 3.2 

(\x -> x+1) 3 

• User can restrict the type, e.g.

inc :: Int -> Int

• In that case, some examples may be wrongly typed.


inc 3.2 

inc 3 

CS5205 Haskell 25
Function Abstraction

• Function abstraction is the ability to convert any


expression into a function that is evaluated at a later
time.

<Expr> p = \ () -> Expr

time

time p ()

Normal Execution Delayed Execution

CS5205 Haskell 26
Higher-Order Functions
• Higher-order programming treats functions as first-class,
allowing them to be passed as parameters, returned as
results or stored into data structures.

• This concept supports generic coding, and allows


programming to be carried out at a more abstract level.

• Genericity can be applied to a function by letting


specific operation/value in the function body to become
parameters.

CS5205 Haskell 27
Functions
• Functions can be written in two main ways:
add :: Integer -> Integer -> Integer
add x y = x+y

add2 :: (Integer,Integer) -> Integer


add2(x,y) = x+y

• The first version allows a function to be returned as


result after applying a single argument.
inc :: Integer -> Integer
inc = add 1

• The second version needs all arguments. Same effect


requires a lambda abstraction:
inc = \ x -> add2(x,1)
CS5205 Haskell 28
Functions
• Functions can also be passed as parameters. Example:
map :: (a->b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : (map f xs)

• Such higher-order function aids code reuse.


map (add 1) [1, 2, 3] ) [2, 3, 4]
map add [1, 2, 3] ) [add 1, add 2, add 3]

• Alternative ways of defining functions:


add = \ x -> \ y -> x+y
add = \ x y -> x+y

CS5205 Haskell 29
Genericity
• Replace specific entities (0 and +) by parameters.

sumList ls =
case ls of
[] -> 0
x:xs -> x+(sumList xs)

foldr f u ls =
case ls of
[] -> u
x:xs -> f x (foldr f u xs)
CS5205 Haskell 30
Polymorphic, Higher-Order Types

sumList :: [Int] -> Int

sumList :: Num a => [a] -> a

foldr :: (a -> b -> b) -> b


-> [a] -> b

CS5205 Haskell 31
Instantiating Generic Functions

sumL2 :: Num a => [a] -> a


sumL2 ls = foldr (+) 0 ls

sumL2 [1, 2, 3] )

sumL2 [1.1, 3, 2.3] )

CS5205 Haskell 32
Instantiating Generic Functions

prodL :: Num a => [a] -> a


prodL ls = foldr (*) 1 ls

prodL [1, 2, 5] )

prodL [1.1, 3, 2.3] )

CS5205 Haskell 33
Instantiating Generic Functions
• Can you express map in terms of foldr?
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : (map f xs)

map f xs = foldr … … … xs

CS5205 Haskell 34
Instantiating Generic Functions
• Filtering a list of elements with a predicate.
filter :: (a -> Bool) -> [a] -> [a]
filter f [] = []
filter f (x:xs) =
if (f x) then x : (filter f xs)
else x : filter f xs

• Can we express filter in terms of foldr?


filter f xs = foldr … … … xs

CS5205 Haskell 35
Pipe/Compose

compose :: (b -> c) -> (a -> b)


-> a -> c
compose f g = \ x -> f (g x)
g | f = compose f g

• Similar to Unix pipe command:

cmd1 | cmd2

CS5205 Haskell 36
Iterator Construct

for :: Int -> Int -> (Int -> a -> a)


-> a -> a
for i j f a =
if i>j then a
else f (i+1) j (f i a)

• In Haskell, type class help give a more generic type:


for :: Num b, Ord b => b -> b ->
(b -> a -> a) -> a -> a

CS5205 Haskell 37
Right Folding

foldr f u [x1,x2,..,xn]

 f x1 (foldr f u [x2 ..xn])


 f x1 (f x2 (fold f u [x3..xn]))

 f x1 (f x2 (… (fold f u [xn]) …))


 f x1 (f x2 (… (f xn u) …)))

associate to
right
CS5205 Haskell 38
Left Folding – Tail Recursion
• Accumulate result in a parameter:

foldl f u ls =
case ls of
[] -> u
x:xs -> foldl f (f u x) xs

based on accumulation
• What is the type of foldl?

• Can we compute factorial using it?

CS5205 Haskell 39
Left Folding

foldl f u [x1,x2,..,xn]

 foldl f (f u x1) [x2 ..xn]


 foldl f (f (f u x1) x2) [x3..xn]))

 foldl f (f … (f (f u x1) x2)… xn) []


 f (… (f (f u x1) x2) …) xn

left is here!
CS5205 Haskell 40
Instance of Left Folding
• Summing a list by accumulation.

sumT acc ls =
case ls of
[] -> 0
x:xs -> sumT (x+acc) xs

sumList ls = sumT 0 ls

sumT acc ls = foldl (+) acc ls

CS5205 Haskell 41
Infix Operator
• Infix operators are distinguished entirely by symbols:
(++) :: [a]-> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)

• Another example is function composition.


(.) :: (b->c) -> (a->b) -> (a->c)
f . g = \ x -> f (g x)

• Infix operator can be coerced to prefix by bracketing,


e.g. map (+) [1,2,3]

• Alphanumeric named function can be made infix too,


e.g. a ‘add’ b x ‘elem’ xs
CS5205 Haskell 42
Sections
• Infix operators can also be partially applied:
(x+) ´ \y -> x+y
(+y) ´ \x -> x+y
(+) ´ \x y -> x+y

• Other examples:.
inc = (+ 1)
add = (+)

• These are syntactic sugar for programming


conveniences.

CS5205 Haskell 43

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy