Unit1 - Haskell
Unit1 - Haskell
PRINCIPLES OF PROGRAMMING
LANGUAGES
D R . E . SO PHIYA
ASSISTAN T PR OF E SSOR/ CSE
AM R ITA VISHWA VID YAPEE THAM
Unit 1
Programming Paradigms – Overview of different programming paradigms.
Functional Programming with Haskell –functions and types, functional
composition, numbers, lists, tuples, type classes, pattern matching, higher order
functions: currying, lambdas, maps and filters, folds, IO monad
Unit 2
Concurrency in Java - Issues with concurrency: safety, liveness, fairness,
Threads, locks and synchronization, Thread pools, Futures and callables, fork-join
parallel framework
Unit 3
Functional Programming overview with Scala – Basic types and operations,
classes and objects, functional objects, functions and closure, composition and
inheritance
III CSE B
2
Unit 1
Programming Paradigms
Programming paradigms are different ways or styles in which a given
program or programming language can be organized.
Each paradigm consists of certain structures, features, and opinions about
how common programming problems should be tackled.
You can't "build" anything with a paradigm. They're more like a set of ideals
and guidelines.
Programming languages aren't always tied to a specific paradigm.
Enforced by compiler during compilation
III CSE B
3
Overview of different
programming paradigms
Imperative: Programming with an explicit sequence of commands.
Control flow in imperative programming is explicit.
◦ defines the solution to a problem as a series of steps
◦ individual statements, instructions, or function calls.
◦ how to achieve the goal
III CSE B
4
Finding the sum of all the numbers in
our list.
IMPERATIVE DECLARATIVE
III CSE B
5
Imperative Programming Declarative Programming
Computation describe the step-by-step instructions for set the conditions that trigger the program
how an executed program achieves the execution to produce the desired results.
desired results.
Readability and add more features and code to your less complex and requires less code, making it
complexity program, it can become longer and more easier to read.
complex, making it increasingly confusing
and time-consuming to read.
Customization have complete control to edit and can easily Customizing the source code is more difficult
adapt the structure of your program to your because of complicated syntax and the
needs. paradigm’s dependence on implementing a
pre-configured algorithm.
Optimization Adding extensions and making upgrades are You can easily optimize code because an
supported, but doing so is significantly more algorithm controls the implementation.
challenging than with declarative Furthermore, you can add extensions and
programming, making it harder to optimize. make upgrades.
Structure The code structure can be long and complex. The code structure is concise and precise, and
The code itself specifies how it should run it lacks detail. Not only does this paradigm
and in what order. Due to the increased vastly limit the complexity of your code, but
complexity, the code can sometimes be the code is more efficient.
confusing because it may perform more than
one task.
III CSE A 6
III CSE B 7
Procedural Programming
Follows imperative programming with procedural calls referred as function,
method or subroutines.
Each function performs specific operation.
These calls direct the system to perform the required tasks.
Each procedure or so-called function can have multiple commands to be
executed.
The function, once defined, can be called as many times as needed.
Example: program that gives us factorial of a number
Languages: C, Java, Python, Pascal, PHP
III CSE B
8
It's simple. The program is very unique
An easier way to keep track of program is static and not expected to
program flow. change much over time
It has the ability to be strongly None or only a few features are
modular or structured. expected to be added to the project
over time
Needs less memory: It's efficient and
effective.
III CSE B 9
Object Oriented Programming
In OOP programming, all the
program components are represented
as objects. hide
Redefine by many forms
group
An object binds the data and the
associated methods together as
single unit.
The programmer can control the data
access permissions by defining the
share
access specifier.
Languages: C++, Java, Python, VB,
Ruby
Attributes and behavior
III CSE B 10
Example: find the sum of first ten natural numbers
public class Main
{
public static void main(String[] args) {
Addition obj = new Addition();
obj.num = 10;
int answer = obj.addValues();
System.out.println("The sum is = "+answer); //prints-> The sum is 55
}
}
class Addition {
int sum =0;
int num =0;
int addValues(){
for(int i=1; i<=num;i++){
sum += i;
}
return sum;
}}
III CSE B 11
Reuse of code through Inheritance. a lot of code that could be shared
and reused
Flexibility through Polymorphism.
project is anticipated to change often
High security with the use of and be added to over time
Encapsulation and Abstraction
mechanisms.
III CSE B 12
Parallel processing
processing of program instructions by dividing them among multiple
processors.
A parallel processing system allows many processors to run a program in less
time by dividing them up.
Languages: C, C++
Speeds up performance.
divide and conquer method
a system that has more than one CPU or multi-core processors
real-world data that needs more dynamic simulation and modeling
III CSE B
13
Declarative:
Logic programming
Based on formal logic
isn't made up of instructions - rather it's made up of facts and rules
Execution of the program is very much like proof of mathematical statement
Languages: Prolog, ALF, Alice, Ciao
Example:
man(Socrates). // fact: object `Socrates' is a man
mortal(X) :- man(X). // rule: "X is mortal if X is a man;''
?- mortal(Socrates). //query: "Is Socrates mortal?''
III CSE B
14
Easy to implement the code. Projects like theorem proving, expert
systems, term rewriting, type
Debugging is easy. systems and automated planning
it's structured using true/false
statements, we can develop the
programs quickly using logic
programming.
III CSE B 15
Functional programming
Execution of series of mathematical Example:
functions.
function isPrime(number){
All code is within a function.
for(let i=2;
All variables are scoped to the function. i<=Math.floor(Math.sqrt(number)); i++){
Functions do not modify any values outside if(number % i == 0 ){
the scope of that function.
return false;
Languages: Haskell, Scala, Clojure, Racket,
JavaScript, Erlang, Lisp }
}
return true;
}
isPrime(15);
III CSE B 16
Functions can be coded quickly and Working with mathematical
easily. computations.
General-purpose functions can be Applications aimed at concurrency or
reusable which leads to rapid parallelism.
software development.
Unit testing is easier.
Debugging is easier.
III CSE B 17
Database processing
A database is an organized collection Example:
of structured information, or data
CREATE DATABASE personalDetails;
controlled by a database
management system (DBMS) CREATE TABLE Persons (
III CSE B 18
Massive amount of data is handled Accessing, modifying, updating data
on the database.
Easy to validate and ensure the
consistency of data Communicating with servers.
Easy to update data
III CSE B 19
Functional Programming with
Haskell
Programs are functions
Functions transform input values into output values
lambda calculus
Functional Programming is a set of function definitions (Declarative)
Computation is a process of applying rules
Haskell – writing provably correct code
Rapid prototyping – Specification to implementation
III CSE B 20
Haskell is lazy.
◦ won't execute functions and calculate things until it's really forced to show you a
result
III CSE B
21
Installation
• https://www.haskell.org/downloads/
• ghc's interactive mode and call some function to get a very basic feel for haskell.
• Open your terminal and type in ghci.
III CSE B
22
GHC stands for Glasgow Haskell Compiler.
GHC is completely written in Haskell.
GHC supports parallel and concurrent programming, profiling for time and
space.
III CSE B
23
Simple arithmetic
Evaluate any kind of Haskell expressions in interactive mode.
Operator Performs
+ Addition
- Subtraction
* Multiplication
/ Division
mod Get the remainder
rem Get the remainder, Sign of the result is
same as sign of x.
^ Calculates power, a^x return a to the power
x.
III CSE B
24
C:\Users\Sophiya>ghci
GHCi, version 9.2.5: https://www.haskell.org/ghc/ :? for help
ghci> 10+5
15
ghci> 10-5
5
ghci> 10*5
50
ghci> 10/5 or div 10 5
2.0
ghci> mod 10 5
0
ghci> rem 10 5
0
ghci> mod 5 10
5
ghci> rem 5 10
5
ghci> 10 ^ 5
100000
Always surround negative numbers in parenthesis
ghci> 10/(-3)
-3.3333333333333335
III CSE B
25
let - key word is used to define variables, functions in Haskell interpreter.
III CSE B 26
Boolean operators
ghci> True && True
True
ghci> True && False
False
ghci> True || True
True
ghci> False || True
True
ghci> False || False
False
ghci> True || (5>12)
True
ghci> not True
False
ghci> not False
True
III CSE B 27
Haskell Function
Function description has two parts: Following are the naming conventions
◦ Data type of inputs and outputs to a function in Haskell
◦ Rule for computing output from inputs a. Function name must start with a
Example: lower case letter.
Type definition:
function name :: Type ->Type
b. List of parameters to a function
also start with a lower case letter
add :: Int ->Int
Rule: c. Better to follow camel case
add x y = x+y convention, while defining function
name, parameter names.
Example:
cube x = x * x * x Ex:
sumOfNumbers arg1 arg2 = arg1 +
arg2
III CSE B
28
Haskell functions take more priority than anything else.
ghci> let square x=x*x
ghci> square 5*2
50
III CSE B 29
The succ function takes anything that has a defined successor and returns
that successor.
ghci> succ 5
6
ghci> succ(succ 5)
7
ghci> min 2 3
2
ghci> max 1 10
10
III CSE B
30
ghci> (1+) 2 // successor function (\y->1+y)
3
ghci> (1/) 2 // reciprocation function
0.5
ghci> (*2) 2 // doubling function
4
ghci> (/2) 4 // halving function
2.0
III CSE A
31
Example Function
1. calculate simple interest.
Let Principal = P, Rate = R% per annum (p.a.) and Time = T years. Then,
Simple Interest = (P x R x T)/100
Open any text editor and type rule, save it as interest.hs. Haskell files stored with .hs extension.
p = 10000
r= 2
t=2
interest = (p*t*r)/100
Go to the directory, where your interest.hs is located and type the command ghci.
‘:load’ command is used to load Haskell file. You can use :l in short cut to load Haskell files (:l hello.hs).
Observe above code snippet, when the file is loaded, Haskell changes the prompt from prelude to *Main. You can use the
variables defined in interest.hs in *Main prompt.
ghci> :load interest.hs
III CSE B
32
2. Find maximum of three numbers: if-else, max
III CSE B 33
Following are the basic numeric types supported by Haskell. All these numeric
types are instances of Num.
Type Description
Int It is bounded integer type, represent integer values
Float Single precision floating point value. Used to represent real numbers
like 10.32, 9.86 etc., Usage of Float is discouraged, since Haskell
compilers are written Double data type efficient code.
Double Double precision floating point value. Used to represent real numbers
like 10.32, 9.86 etc.,
III CSE B 34
type
Haskell is statically typed language
For statically typed languages, type of the variable is known at compile time.
Haskell Infer the types
If you don't specify type to a variable (or) any function, then Haskell automatically deduce the types.
ghci> let a =1
ghci> let b="xxx"
b :: String
ghci> :t c
c :: Bool
ghci> :t 5.4
5.4 :: Fractional a => a
ghci> :t 'x'
'x' :: Char
III CSE B 35
functions has types as well
ghci> :t (&&)
(&&) :: Bool -> Bool -> Bool
ghci> add x y =x+y
ghci> sub x y =x-y
ghci> :t add
add :: Num a => a -> a -> a
ghci> :t sub
sub :: Num a => a -> a -> a
III CSE B
36
Function composition
A function output can be passed as input to other function. Combining functions
by passing output of one function as input to other function is called composition
of functions.
composition is denoted by f{g(x)} where g() is a function and its output in
used as an input of another function, that is, f().
For example,
then
f(g(x)) = f(2x) = 2x + 1
III CSE B 38
List Functions
List in Haskell cannot be of mixed types
Example: [1,2, True] or [1, ‘a’, False]
List can be specified with its Type [T]
Example: [1,2,3,4]:: [Int]
[True, false]::[Bool]
[] empty list
List can be nested.
[[3,2]] :: [[Int]]
III CSE B 39
Prepend elements to a list:
ghci> 5:[]
using ‘:’ cons operator you can prepend
and element to a list. [5]
It adds a single element to ghci> 4:[5]
the beginning of a list (and returns a
new list). [4,5]
[1,2,3,4,5] [2,3,4,5]
III CSE B
40
Combine two lists
By using ++ operator, you can append one list to other. //known number of lists
(++) :: list1 -> list2 -> joined-list
(++) :: [a] -> [a] -> [a]
Prelude> let even =[2,4,6,8]
Prelude> let evenodd = even ++ odd //[1,2,3] ++ [4]
Prelude> evenodd
[2,4,6,8,1,3,5,7,9]
III CSE A 41
Access elements of a list
By using !! double-bang operator, you can access the elements of a list.
Elements indexed from 0.
!! 0 returns first element in the list
!! 1 returns second element in the list.
Prelude> odd_numbers
[1,3,5,7,9]
Prelude>
Prelude> odd_numbers !! 0
1
Prelude> odd_numbers !! 1
3
Prelude> odd_numbers !! 2
5
III CSE B
42
Decomposing lists
X:XS
last: Return last element of a list
head: Get first element of the list
last takes a list and return the last element
head takes a list and return first element of the list. of list.
//last :: [a] -> a
Head (X:XS) -> X //head :: [a] -> a
[3,5,7,11]
III CSE B 43
init: Return a list by excluding last element //init :: [a] -> [a]
init takes a list and return new list by excluding the last element.
Prelude> init primes
[2,3,5,7]
length: Get length of the list // length :: Foldable t => t a -> Int
length takes a list and return number of elements in the list.
Prelude> length primes
5
null: Check for list emptiness // null :: Foldable t => t a -> Bool
null takes a list and return True if list is empty, else False.
Prelude> null primes
False
drop: Drop elements from beginning of a list //drop :: Int -> [a] -> [a]
drop takes a number n and a list, return a new list by dropping first n elements.
Prelude> drop 2 primes
[5,7,11]
maximum: Get maximum element from a list // maximum takes a list and return
maximum element in the list.
Prelude> maximum primes
11
III CSE B 45
sum: Get sum of elements in the list
sum takes a list of numbers and return sum of elements in the list.
Prelude> sum primes
28
cannot specify more than the first two elements and the upper bound:
ghci> [1,3,5..10]
<interactive>:38:7: error: parse error on input `..‘
III CSE B 47
Be careful when using ranges with floating-point values, because it accepts spill-
overs up to half-delta, to fend off rounding issues:
ghci> [1.0,1.5..2.4]
[1.0,1.5,2.0,2.5]
ghci> [1.0,1.1..1.2]
[1.0,1.1,1.2000000000000002]
Step difference
[1,3..8] = [1,3,5,7]
[2,5..19]=[2,5,8,11,14,17]
[8,7..5]=[8,7,6,5]
[12,8..-9]=[12,8,4,0,-4,-8]
Prelude> ['a'..'z']
"abcdefghijklmnopqrstuvwxyz“
returns the numbers in the same set that are equal or larger than 10
ghci> [x|x<-[1..10],x*2>=10]
[5,6,7,8,9,10]
ghci> [x|x<-[1..10],x*2<=10]
[1,2,3,4,5]
III CSE B 49
Comprehensions can have multiple generators, separated by commas.
cross product of two lists.
ghci> [(x,y)|x<-[1,2,3],y<-[1,2,3]]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
Dependant Generators
Later generators can depend on the variables that are introduced by
earlier generators.
ghci> [(x,y) | x <-[1..3], y <-[x..3]]
[(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)]
III CSE B 50
[x*x | x <- [1..5], isPrime x]
[4,9,25]
III CSE A 51
Zipping and Unzipping Lists
zip takes two lists and returns a list of corresponding pairs
zip :: [a] -> [b] -> [(a, b)]
zip (a:as) (b:bs) = (a,b) : zip as bs
ghci> zip [1,2,3][4,5,6]
[(1,4),(2,5),(3,6)]
unzip function, which takes a list of tuples and returns two lists, one with all the first
components and other one with the seconds
unzip :: [(a, b)] -> ([a], [b])
ghci> unzip [(1,2),(2,3),(3,4)]
([1,2,3],[2,3,4])
List Transformations
Use Library:
ghci> import Data.List
III CSE A 52
Transpose: takes a list of lists, which we can think of as a "matrix". Then it transposes the
matrix so that the rows are now the columns.
transpose :: [[a]] -> [[a]]
transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
transpose [[1],[4,5],[7,8,9]]
[[1,4,7],[5,8],[9]]
transpose ["ABCD","abcd"]
["Aa","Bb","Cc","Dd"]
intersperse 0 [1,2,3,4]
[1,0,2,0,3,0,4]
III CSE A 54
Strings are lists of characters internally
III CSE B 55
repeat: Produce infinite list
repeat takes an element and produces an infinite list of just that element.
ghci> [ x | x <- "The quick brown fox jumps over the lazy dog.", x `elem` "aeiouy" ]
"euioouoeeayo"
III CSE A 57
Tuples
Supports multiple types of data together.
to define a tuple: use parentheses () with elements delimited by commas
Example:
Student Information: Name, Reg.no, Branch, etc.
ghci> let stud =("Hari",1001,"CSE")
ghci> stud
("Hari",1001,"CSE")
List of Marks for a course
ghci> let students=[("xxx", 97), ("xyy", 91)]
ghci> students
[("xxx",97),("xyy",91)]
Tuple types:
(1, True) :: (Int, Bool)
([1,2],3) :: ( [Int], Int)
III CSE B
58
ghci> students !! 0
("xxx",97)
ghci> students !! 1
("xyy",91)
Nested tuples
Just like lists, a tuple can has other tuple in it.
ghci> ((1,1),(2,2),(3,3))
((1,1),(2,2),(3,3))
ghci> (('a','b','c','d'))
('a','b','c','d')
III CSE B 59
zip: Map two lists as list of tuples
zip takes two lists, it creates a list of tuples by joining the matching elements into pairs.
ghci> let list1=[1,2,3,4,5]
ghci> let list2=[5,4,3,2,1]
ghci> zip list1 list2
[(1,5),(2,4),(3,3),(4,2),(5,1)]
III CSE B 60
types
Type can be considered as a value
Int type includes 1,2,..
Bool type includes True/False
But how do we make our own?
▪use the data keyword to define a type.
Syntax: data Type = Constructor1 | Constructor2
constructors - specify the different values that this type can have.
Example:
To create a Bool type
data Bool = False | True
Both the type name and the value constructors have to be capital cased.
III CSE B
61
Algebraic data types
Sum Types:
▪Represent a value that can be one of several possible choices.
data Bool = False | True type constructor - name of our
Data Cards = Hearts | Diamonds | Clubs | Spades type
data constructor - used to
Product Types: construct new instances of the
▪combine multiple values into a single value. type
▪Syntax: data Typeconstructor = dataconstructor Types wrapped
▪ values are stored as fields within a data constructor.
data Shape = Circle Float Float Float
first two fields are the coordinates of its center, the third one its radius
data Person = Person String Int
a person with a name and an age
III CSE A
62
Sum and Product Types:
Combine sum and product types to create more complex data structures.
data Shape = Circle Float Float Float | Rectangle Float Float Float Float
Circle and Rectangle are different constructors representing different shapes
Rectangle: the first two are the coordinates to its upper left corner and the
second two are coordinates to its lower right one.
data Employee = Manager String Int | Developer String Int
Manager and Developer are constructors each containing a name and an
employee ID.
III CSE A
63
Maybe:
A function might not be able to return a value for a certain input.
ghci> :info Maybe
type Maybe :: * -> *
data Maybe a = Nothing | Just a
If the function succeeds, we wrap the result in Just. Otherwise, we return
Nothing, which symbolizes something similar to null.
III CSE A
64
ghci> :cd F:\Amrita\Class Works\Dec 2023\PPL\class practice
ghci> :load types.hs
[1 of 2] Compiling Main ( types.hs, interpreted )
head' :: [a] -> Maybe a Ok, one module loaded.
III CSE A
65
Shape
Examples:
Write a function that takes a shape and returns its surface.
data Shape = Circle Float Float Float | Rectangle Float Float Float Float
surface :: Shape -> Float
surface (Circle _ _ r) = pi * r ^ 2
surface (Rectangle x1 y1 x2 y2) = abs (x2-x1) * abs (y2-y1)
ghci> surface $ Circle 10 20 10
314.15927
ghci> c= Circle 10 20 10
ghci> surface c
314.15927
III CSE A 66
ghci> surface $ Rectangle 1 1 4 5
12.0
ghci> r= Rectangle 1 1 4 5
ghci> surface r
12.0
ghci> Circle 10 20 10
<interactive>:43:1: error:
* No instance for (Show Shape) arising from a use of `print'
* In a stmt of an interactive GHCi command: print it
Deriving Instances: can automatically derive instances for your types
data Type = Constructor1 | Constructor2 deriving (Eq, Show)
if we add deriving (Show) at the end of a data declaration, Haskell automagically makes that
type part of the Show typeclass
data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving (Show)
ghci> Circle 10 20 10
Circle 10.0 20.0 10.0
III CSE A
67
Value constructors are functions, so we can map them and partially apply them and everything
If we want a list of concentric circles with different radii, we can do using map.
ghci> let circles = map (Circle 10 20) [3,4,5,6]
[Circle 10.0 20.0 3.0,Circle 10.0 20.0 4.0,Circle 10.0 20.0 5.0,Circle 10.0 20.0 6.0]
ghci> let surfacecircles = map surface circles
ghci> surfacecircles
[28.274334,50.265484,78.53982,113.097336]
Similarly, If we want a list of rectangles with different right corners:
ghci> let rect =map (\ (x,y) -> Rectangle 1 1 x y) [(3,4),(4,5)]
ghci> rect
[Rectangle 1.0 1.0 3.0 4.0,Rectangle 1.0 1.0 4.0 5.0]
ghci> let surfacerect = map surface rect
ghci> surfacerect
[6.0,12.0]
III CSE A
68
Let’s make an intermediate data type that defines a point in two-dimensional
space.
So now the Circle has two fields, one is of type Point and the other of type Float. Same
goes for the rectangle.
III CSE A 70
ghci> let x = Person "John" "dalton" 65 184.0 "98756xxxxx"
ghci> x
Person "John" "dalton" 65 184.0 "98756xxxxx“
The main benefit of this is that it creates functions that lookup fields in the data type. By
using record syntax to create this data type, Haskell automatically made these functions:
firstName, lastName, age, height and phoneNumber.
III CSE A 71
ghci> 2+3
5
ghci> 2.0+3.0
5.0
+ operator works for a bunch of different underlying data types.
ghci> 2==2
True
ghci> 2==5
False
ghci> [2,5] == [2,5]
True
== operator can compare all sorts of values
operator “overloading” to support ad–hoc polymorphism.
III CSE A
72
Operator function for +
(+) :: Integer -> Integer -> Integer
(+) :: a -> a -> a
Qualified Types
ghci> :t (+)
(+) :: Num a => a -> a -> a
+ takes in two a values and returns an a value for any type a that is a Num or is an
instance of Num.
The name Num can be thought of as a predicate over types.
Some types satisfy the Num predicate.
Examples:
int, Integer, Double etc, and any values of those types can be passed to +
III CSE A
73
Other types do not satisfy the predicate.
Examples: Char, String, functions etc, and so values of those types cannot be
passed to +.
ghci> 'a' + 'c'
<interactive>:19:5: error:
* No instance for (Num Char) arising from a use of `+'
III CSE A 74
Type Classes
A typeclass is a collection of operations (functions) that must exist for the
underlying type.
Example:
Num Typeclass includes int, Integer, Float, Double..
A type has an instance of a typeclass if it implements the methods of that
typeclass.
A generic interface that contain common operations applicable to number of
types.
III CSE A
75
Type Class
A type class is a set of functions,
along with their type signature. By
using the keyword ‘class’, you can Example:
define a type class. To know about Num class
Syntax ghci> :info Num
type Num :: * -> Constraint
class TypeClassName a where class Num a where
function1 :: type1 (+) :: a -> a -> a
(-) :: a -> a -> a
function2 :: type2
(*) :: a -> a -> a
.... negate :: a -> a
.... abs :: a -> a
signum :: a -> a
functionN :: typeN fromInteger :: Integer -> a
III CSE B 76
Num ghci> :t (*)
(*) :: Num a => a -> a -> a
Num is a numeric typeclass. ghci> 5* (6 :: Integer)
30
Its members have the property of ghci> :type it
being able to act like numbers. it :: Integer
ghci> :t 20 ghci> (5::Int) * (6:: Int)
30
20 :: Num a => a ghci> (5::Int) * (6:: Integer)
<interactive>:30:13: error:
ghci> 20 :: Int
* Couldn't match expected type `Int' with
20 actual type `Integer‘
ghci> (5::Int) + (6:: Int)
ghci> 20:: Integer 11
20
ghci> (5::Int) + (6.0:: Float)
ghci> 20 :: Float <interactive>:36:13: error:
* Couldn't match expected type `Int' with
20.0 actual type `
ghci> 20 :: Double
ghci> (5::Int) + (6:: Integer)
20.0 <interactive>:37:13: error:
III CSE A 77
ghci> 5+2
7 Standard addition, generally understood as
ghci> 5-3 associative and commutative
2
ghci> 5*3 a + (b + c) ≡ (a + b) + c
15 a+b≡b+a
ghci> negate 5
-5 Multiplication, an associative operation that's
ghci> abs (-5) distributive over addition
5
ghci> abs (5) a * (b * c) ≡ (a * b) * c
5 a * (b + c) ≡ a * b + a * c
ghci> 5+(3+2)
10
ghci> signum 5
1
ghci> signum 0
0
ghci> signum 5 * abs 5
5
III CSE A 78
EQ type class is an interface which provides the functionality to test the equality of an
expression. Any Type class that wants to check the equality of an expression should be a
part of this EQ Type Class.
ghci> :info Eq ghci> 2 == 2
type Eq :: * -> Constraint True
class Eq a where ghci> 2 /= 2
False
(==) :: a -> a -> Bool
ghci> 'a' == 'a'
(/=) :: a -> a -> Bool True
instance Eq Bool -- Defined in `GHC.Classes' ghci> "amrita" == "amrita"
instance Eq Char -- Defined in `GHC.Classes' True
instance Eq Double -- Defined in `GHC.Classes' ghci> "Amrita" == "AMrita"
instance Eq Float -- Defined in `GHC.Classes' False
instance Eq Int -- Defined in `GHC.Classes' ghci> 3.14 == 3.14
instance Eq Ordering -- Defined in `GHC.Classes' True
instance Eq a => Eq (Solo a) -- Defined in `GHC.Classes' ghci> 5+(3+2) == (5+3)+2
instance Eq Word -- Defined in `GHC.Classes' True
instance Eq a => Eq [a] -- Defined in `GHC.Classes' ghci> 5*(3+5) == (5*3) + (5*5)
instance Eq a => Eq (Maybe a) -- Defined in `GHC.Maybe' True
instance (Eq a, Eq b) => Eq (Either a b) ghci> 5*(3*3) == (5*3)*3
True
III CSE B
79
Ord is for types which gives us the functionality of ordering.
ghci> :info Ord
▪ Ord covers all the standard comparing
type Ord :: * -> Constraint
class Eq a => Ord a where functions such as >, <, >= and <=.
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool ▪ The compare function takes
(<=) :: a -> a -> Bool
two Ord members of the same type and
(>) :: a -> a -> Bool
(>=) :: a -> a -> Bool returns an ordering.
max :: a -> a -> a
min :: a -> a -> a ▪ Ordering is a type that can
instance Ord Bool -- Defined in `GHC.Classes'
instance Ord Char -- Defined in `GHC.Classes' be GT, LT or EQ
instance Ord Double -- Defined in `GHC.Classes'
instance Ord Float -- Defined in `GHC.Classes'
instance Ord Int -- Defined in `GHC.Classes'
instance Ord Ordering -- Defined in `GHC.Classes' data Ordering = LT | EQ | GT
instance Ord a => Ord (Solo a) -- Defined in `GHC.Classes'
instance Ord Word -- Defined in `GHC.Classes' compare :: Ord a => a -> a -> Ordering
instance Ord a => Ord [a] -- Defined in `GHC.Classes'
instance Ord a => Ord (Maybe a) -- Defined in
`GHC.Maybe'
instance (Ord a, Ord b) => Ord (Either a b)
-- Defined in `Data.Either'
III CSE B
80
ghci> 5>=7
ghci> "ABCDEF" `compare` "ABCD" False
GT
ghci> 12 `compare` 5 ghci> 7<=9
GT True
ghci> 5 `compare` 12
LT ghci> 3.9 > 9.0
ghci> 5 `compare` 5 False
EQ
ghci> "ABCD" `compare` "AMRITA" ghci> 'k' < 'z'
LT True
ghci> min 5 3
3 ghci> [1,2,3,4] <= [1,2,3,4]
ghci> max 10 12 True
12
ghci> 4<5 ghci> Just 5 <= Just 4
True False
ghci> 5> 3
True ghci> Nothing < Just 100
True
ghci> Nothing `compare` Nothing
EQ
III CSE A 81
Show has a functionality to print its argument as a String. Whatever may be its argument, it
always prints the result as a String.
ghci> :info show ghci> show (5==5)
type Show :: * -> Constraint "True“
class Show a where
... ghci> show (12 `compare` 5)
show :: a -> String "GT"
...
ghci> 5*3
ghci> show 310 15
"310"
ghci> show 10.56 ghci> show (5*3)
"10.56" "15“
ghci> show True
"True" ghci> show [x*2|x<-[1..10],even x]
ghci> show [1,2,3] "[4,8,12,16,20]“
"[1,2,3]"
ghci> show ['a'] ghci> show (3,'a')
"\"a\"" "(3,'a')“
ghci> show ['h','e','l','l','o']
"\"hello\"“ ghci> map show [x*2|x<-[1..10],even x]
["4","8","12","16","20"]
III CSE B
82
Read is sort of the opposite typeclass of Show. The read function takes a string and returns a
type which is a member of Read.
III CSE A 83
Enum members are sequentially ordered types — they can be enumerated.
▪Can use its types in list ranges.
▪Have defined successors and predecesors.
▪Types in this class: (), Bool, Char, Ordering, Int, Integer, Float and Double.
ghci> :info Enum
type Enum :: * -> Constraint
class Enum a where
succ :: a -> a
pred :: a -> a
toEnum :: Int -> a
fromEnum :: a -> Int
enumFrom :: a -> [a]
enumFromThen :: a -> a -> [a]
enumFromTo :: a -> a -> [a]
enumFromThenTo :: a -> a -> a -> [a]
III CSE B
84
ghci> [1..5] ghci> mylist = enumFromThen 4 6
[1,2,3,4,5] ghci> take 10 mylist
ghci> ['a'..'k'] [4,6,8,10,12,14,16,18,20,22]
"abcdefghijk“
ghci> [LT .. GT] ghci> mylist1 = enumFromThen 6 2
[LT,EQ,GT] ghci> take 8 mylist1
ghci> succ 'A' [6,2,-2,-6,-10,-14,-18,-22]
'B'
ghci> succ 6 ghci> enumFromTo 6 10
7 [6,7,8,9,10]
ghci> pred 10
9 ghci> enumFromTo 10 6
ghci> pred 'z' []
'y‘
ghci> enumFromThenTo 6 8 20
ghci> list = enumFrom 1 [6,8,10,12,14,16,18,20]
ghci> take 5 list
[1,2,3,4,5] ghci> enumFromThenTo 6 5 1
[6,5,4,3,2,1]
III CSE A 85
class BasicEq a where
ghci> isEqual 3 3
isEqual :: a -> a -> Bool
instance BasicEq Bool where
<interactive>:66:1: error:
isEqual True True = True * Ambiguous type variable `a0' arising from a
isEqual False False = True use of `isEqual'
prevents the constraint `(BasicEq a0)' from
isEqual _ _ = False being solved.
III CSE B
87
USING TYPECLASSES
1.Define
An Insert function
Insertion sort
2. showList for Characters
III CSE B 88