0% found this document useful (0 votes)
8 views39 pages

1 Basics

The document provides an overview of Haskell, focusing on its functional programming paradigm, basic syntax, and types. It covers imperative and declarative programming distinctions, introduces the Glasgow Haskell Compiler (GHC), and explains common types and functions in Haskell. Additionally, it discusses type declarations, type variables, and type classes, emphasizing their importance in Haskell programming.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views39 pages

1 Basics

The document provides an overview of Haskell, focusing on its functional programming paradigm, basic syntax, and types. It covers imperative and declarative programming distinctions, introduces the Glasgow Haskell Compiler (GHC), and explains common types and functions in Haskell. Additionally, it discusses type declarations, type variables, and type classes, emphasizing their importance in Haskell programming.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 39

CMPT383 Comparative Programming Languages

Lecture 1: Haskell Basics

Yuepeng Wang
Spring 2025

1
Overview
• Introduction to functional programming

• Haskell compiler and interpreter

• Haskell basics

• Common types in Haskell

• Type declarations

• Type variables

• Type classes
2
Imperative Programming
• For imperative languages, a program gives a sequence of commands/
statements that the computer can execute in order

• The computer maintains a "state" between commands


• Conceptually (in a simplified setting), a state just specifies the values
of all variables

• A command in the program can change the state


• E.g., "int x := 1; x := x+1;" first initializes x to 1 and then changes it to 2

• Example languages: C, C++, Java, Python

3
Declarative Programming
• In some languages, a program does not specify a sequence of commands
SELECT Name, Address, City, Province

FROM Customers

WHERE Country = 'Canada'

• Such programming languages are called declarative languages

• The corresponding programming approach is declarative programming

• A program only specifies what we want to obtain, but not how we can
obtain it

• Example languages: SQL, Datalog, Prolog


4
Functional Programming
• Functional programming is a paradigm where programs are constructed by
applying and composing functions

• It is one type of declarative programming, because a program does not


provide a sequence of commands for execution

• General flavor of functional programming

• The return value of a function is all that matters (no side effects)

• Avoid program states

• Avoid explicit loops (e.g., for, while)


5
Haskell and Its Compiler
• Haskell is a purely functional language, not imperative at all
• Glasgow Haskell Compiler (GHC) is a commonly-used Haskell compiler
• https://www.haskell.org/ghc
• The toolchain includes the GHCi interactive environment (interpreter)
• Read-Eval-Print Loop (REPL), where user inputs are read and
evaluated, and the results are printed to the user
ghci> 1 + 2
3
ghci> 1 + 2 /= 3
False
ghci> reverse [1,2,3]
[3,2,1]

6
Homework 0
• Install the GHC compiler (>= 9.2 recommended)

https://www.haskell.org/ghc/download_ghc_9_2_1.html

• Try the examples in this lecture

• No submission

7
Using GHCi
• In GHCi, we can use ":l" to load a file containing Haskell source code

ghci> :l test.hs

[1 of 1] Compiling Main ( test.hs, interpreted )

Ok, one module loaded.

• We can use ":r" to reload the file after edit

ghci> :r

Ok, one module loaded.

8
Prelude
• A module called Prelude is loaded to the context by default, for both GHC
and GHCi

• We can view Prelude as a standard library for functions, types, etc.

• Example: +, -, *, reverse, ...

• That is why we can use this stuff

9
Values
• Basic values and types

• Ints (bounded): 4, (-2)

• Integers (unbounded): 1000000000000000000

• Floating points: 4.2

• Booleans: True, False

• Strings: “abc”, “4.2”

• Lists: [1, 2, 3, 4], [“abc”, “def”]

10
Arithmetic Expressions

Expression Result
2-4 -2
2*3+4*5 26
2^3*4 32
4.0 + 2 6.0
4.0 / 2 2.0
4/2 2.0
4 `div` 2 2

11
Logical Expressions

Expression Result

not False True

False || True True

False && True False

4 == 2 False

4 /= 2 True

4 <= 2 False

12
Lists
• Conceptually, Haskell lists are singly-linked lists

• A head tells the current element

• A tail pointer points to the rest of the list

• Lists are surrounded by square brackets, and elements are separated by


commas

• Examples: [ ], [1], [1, 2], [1, 2, 3], ...

13
List Cons
• A common list operation is cons (which means "construct")

• The corresponding Haskell operator is :


• It takes an element E and a list L as input and produces as output a
new list with E prepended to the beginning of L

Expression Result
1 : [2, 3] [1, 2, 3]
1 : (2 : (3 : [ ])) [1, 2, 3]
1:2:3:[] [1, 2, 3]

• The last two rows are the same because the : operator is right-associative

14
List Append
• Another common list operation is append

• The corresponding Haskell operator is ++

• It takes as input two lists and produces as output a new list with the
second list appended to the first

Expression Result
[1, 2] ++ [3, 4] [1, 2, 3, 4]
[ ] ++ [1, 2] [1, 2]
[1, 2] ++ [ ] [1, 2]

15
Characters and Strings
• Characters are surrounded with single quotes

• Strings are surrounded with double quotes

Expression Result

'a' character 'a'

"a" string "a"

"abc" string "abc"

'abc' Error

16
Strings
• Strings are syntactic sugar of lists of characters

• All functions over lists of characters also work for strings!

Expression Result

"ab" ++ "cd" "abcd"


"ab" ++ ['c', 'd'] "abcd"
'a' : "bc" "abc"
"a" : "bc" Error
"ab" == ['a', 'b'] True

17
Functions
• Functions are basic units of functional programming languages

• Haskell has first-class functions

• A function is just a value

• For example, we can assign a function to a variable, just as we can


assign other values to a variable

18
Functions
• In general, Haskell functions use the prefix form

• By default, binary operators (e.g., +, -, *) use the infix form

Mathematics Haskell

f(x) fx
f(x, y) fxy

f(x, y) + 1 f x y + 1 or (f x y) + 1

f(x, g(y)) f x (g y)

f(g(x), y) f (g x) y

19
Functions
• Binary functions to infix form: add backquotes

ghci> div 4 2
2
ghci> 4 `div` 2
2

• Binary operators to prefix form: add parentheses


ghci> 2 + 4
6
ghci> (+) 2 4
6

20
Functions
• Functions are usually defined in a Haskell source file, e.g., test.hs
double x = x * 2
add x y = x + y
list x y = [x, y]

• Then we can use them after loading the file to GHCi


ghci> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, one module loaded.
ghci> double 3
6
ghci> add 2 4
6
ghci> list 2 4
[2,4]
21
What is a Type?
• “A type is an attribute of data which tells the compiler or interpreter how
the programmer intends to use the data”

• It specifies which kind of value can be used, e.g., integers, strings

• It specifies which kind of mathematical, relational, or logical operations


can be applied without causing an error

• Example: equality comparison between integers and boolean values


causes an error, e.g., 1 == True

22
Type Names
• Type names must start with an upper case letter in Haskell

• Function names must start with a lower case letter or underscore

• But underscore by itself is reserved

23
Common Haskell Types
63 63
• Int: bounded, whole numbers, −2 to 2 − 1 for 64-bit machines

• Integer: unbounded, whole numbers

• Float: single-precision floating-point numbers

• Double: double-precision floating-point numbers

• Bool: boolean values: True and False

• Char: denoted by single quotes, Unicode characters

24
Common Haskell Types
• Tuple: definition depends on the length and types of components

• Example: (Int, Char) represents a pair of integer and character

• Example: () is a type that has a single value: ()

• List: homogeneous data structures, denoted by [ ]

• Example: type [Int] represents a list of ints

• Example: [1, ‘a’] causes an error

• String: shorthand for [Char]


25
Examining Types
• We can use :t in GHCi to examine the type of an expression
ghci> :t 'a'
'a' :: Char
ghci> :t True
True :: Bool
ghci> :t "Hello World!"
"Hello World!" :: String
ghci> :t (True, 'a')
(True, 'a') :: (Bool, Char)
ghci> :t 4 == 5
4 == 5 :: Bool

• The :: operator here is read as “has type of”

26
Type Declarations
• A function also has its type, which is different from the return type

• We can provide explicit type declarations (type signatures) when writing


functions
• It is a good practice

• The parameters and the return type are separated by ->

• Example
half :: Float -> Float
half x = x / 2

27
Type Declarations
• We can also specify functions with multiple parameters

• Type of parameter 1 -> … -> Type of parameter n -> Return type


addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z

• To check the type of a function, we can use :t in GHCi


ghci> :t addThree
addThree :: Int -> Int -> Int -> Int

28
Type Variables
• Some functions operate on various types

• For example, list append (++) works on list of integers, characters, etc.

• What is the type of (++)?


ghci> :t (++)
(++) :: [a] -> [a] -> [a]

• What is “a” here?

• “a” is not a specific type

• “a” is called a type variable


29
Type Variables
• Type variables allow functions to operate on values of various types in a
type-safe manner

• Functions that use type variables are called polymorphic functions

• What is the type of cons (:) ?


ghci> :t (:)
(:) :: a -> [a] -> [a]

30
Example: Type Variables
• head is a function from Prelude that takes a non-empty list and returns the
first element ghci> head [1, 2, 3]
1

• What is the type of head?


• head :: [a] -> a

• tail is a function from Prelude that takes a non-empty list and returns a list
with the first element removed ghci> tail [1, 2, 3]
[2, 3]

• What is the type of tail?


• tail :: [a] -> [a]

31
Type Classes
• Sometimes we do not want an arbitrary type. We may need to add some
constraints to the type

• A type class is an interface that defines some behavior

• If a type is an instance of a type class, then it supports and implements


the behavior that type class defines

• Specifically, a type class specifies a set of functions

• Instances of that type class must implement those functions

32
Type Classes
• What is the type of (==)?
ghci> :t (==)
(==) :: Eq a => a -> a -> Bool

• The left-hand side of the => symbol is called a class constraint

• Meaning

• The (==) function takes as input two values of the same type and
returns a boolean value

• The type of those two values must be an instance of the Eq type class

33
Type Class: Eq
• Eq is used for types that support equality comparison

• Its instances implement functions: == and /=

• If there is an Eq constraint on a type variable in a function, it uses == or /=


inside its definition
ghci> :t (/=)
(/=) :: Eq a => a -> a -> Bool
ghci> 42 == 42
True
ghci> 42 /= 42
False

34
Type Class: Ord
• Ord is used for types whose values are in a total order (any two values
are comparable)

• It covers all standard comparison functions such as >, <, >=, and <=

• All the types we have covered so far (except for functions) are instances
of the Ord type class

ghci> :t (>)
(>) :: Ord a => a -> a -> Bool

35
Type Class: Show
• Values whose types are instances of Show can be represented as strings

• All the types we have covered so far (except for functions) are instances
of the Show type class

• The most commonly used function is show


ghci> show 42
"42"
ghci> show 4.2
"4.2"
ghci> show True
"True"

36
Type Class: Read
• The opposite of type class Show. Values whose types are instances of
Read can be constructed from strings

• All the types we have covered so far (except for functions) are instances
of the Read type class

• The most commonly used function is read


ghci> read "42"
*** Exception: Prelude.read: no parse
ghci> :t read
read :: Read a => String -> a
ghci> read "42" :: Int
42

37
Type Class: Num
• Num is a numeric type class. Its instances act like numbers

• Common types: Int, Integer, Float, Double


ghci> :t 42
42 :: Num a => a
ghci> :t (+)
(+) :: Num a => a -> a -> a

38
Type Class: Integral
• Integral is another numeric type class that only includes integral/whole
numbers. It includes types Int and Integer.

• One useful function is fromIntegral: turns an integer into a number


ghci> :t fromIntegral
fromIntegral :: (Integral a, Num b) => a -> b

• Example: the built-in length function returns the length of a list, which has
type of Int
ghci> fromIntegral (length [1, 2]) + 4.2
6.2

39

You might also like