Overview of the Haskell 98 Programming Language (Condensed from Haskell Document by Godisch and Sturm)

Download Report

Transcript Overview of the Haskell 98 Programming Language (Condensed from Haskell Document by Godisch and Sturm)

Overview of the Haskell 98
Programming Language
(Condensed from Haskell Document
by Godisch and Sturm)
How to Run Haskell Programs
• Use the Hugs interpreter downloaded from
www.haskell.org/hugs/
• At the command line, enter hugs
• Haskell script files usually end with a ".hs" extension
• -- indicates a single-line comment
• {-} enclose multi-line comments
• : <command> executes a Haskell command
• All variables and functions start with a lowercase letter
• All types and constructors start with an uppercase letter
Summary of Commands Used in Hugs
Built-in Haskell Data Types
•
•
•
•
•
•
•
Int
Integer
Float
Double
Bool
Char
String
Using the Data Type Int
myFile.hs
functionF :: Int -> Int -> Int
functionF x y = x + y
Inside Hugs Interpreter
Prelude> :load myFile.hs
Main> functionF 1 2
3
Operators Available for Type Int
•
•
•
•
•
•
•
•
•
•
•
5 + 3
5 - 3
5 * 3
5 `div` 3
div 5 3
5 `mod` 2
mod 5 2
5 ^ 3
abs (-5)
Negate (-5)
-5
Integer division (backquotes)
Modulo division
3rd power of 5
Absolute value, parentheses are needed
Negation of -5
Negative 5
Using the Data Type Bool
• Values of type Bool are True or False
functionF :: Int -> Bool
functionF = (>= 7)
• Boolean Operators
True && False
True || False
not True
True == False
True /= False
– logical AND
- logical OR
- logical negation
- equality
- inequality
Using the Data Type Char
• A character is enclosed in a single quote
c :: Char
c = 'a'
• A character can be converted to its ASCII integer
value and vice versa using predefined functions
> ord 'a'
97
> chr 97
'a'
Using the Data Type String
• A string is a (possibly empty) sequence of characters
and is enclosed in double quotes
• It is type synonym for a list of type Char
functionS :: String
functionS = "A string example"
Guards and Pattern Matching
functionG :: Int -> Int
functionG n
| n == 0
= 0
| otherwise
= n - 1
functionH :: Int -> Int
functionH 0
= 0
functionH (n + 1)
= n
Precedence and Binding
• Function application has the highest precedence
• Example: functionF n + 1
– Correct binding: (functionF n) + 1
– Wrong binding: functionF (n + 1)
Indentation and the Offside Rule
• Haskell reduces the need for parentheses to a
minimum by using the offside rule
– To detect the start of another function definition,
Haskell looks for the first piece of text that lies at the
same indentation or to the left of the start of the current
function
• Also, a semicolon can be used to separate several
definitions on the same line
where and let keywords
• Each expression may be followed by a local
definitions using the keyword where
• A similar approach can be done using the
keywords let and in
functionF :: Int -> Int
functionF x = g (x + 1) where
g = (^2)
functionM :: Int -> Int
functionM x = let
functionP = (^2) in functionP (x + 1)
Tuples
• A tuple is a grouping of two or more possibly
different types representing a record or structure
person :: (String, Int)
person = ("Bill", 24)
• A type synonym using the keyword type can be
used to give an alternative name to a type
type Person = (String, Int)
Polymorphic Functions
• A polymorphic function has one definition. It accepts
variables of different types as input at runtime
• Polymorphic types begin with a lowercase letter
functionF :: a -> b -> c -> a
functionF x _ _ = x
• This is different from overloaded functions
– They have many different definitions
– Example is the equality function, which is defined
differently for type Int compared to type Bool
Type Classes
• Members of a type classe are called instances
• Predefined instances of class Eq are Int, Float,
Double, Bool, Char, and String
• Haskell has other built-in classes
–
–
–
–
–
Eq
Ord
Enum
Show
Read
- equality and inequality
- ordering over elements of a type
- enumeration of a type
- conversion of the elements of a type into text
- conversion of values to a type from a string
Function Composition
• The function composition operator is the dot (.)
• It type of the dot is
(b -> c) -> (a -> b) -> (a -> c)
• Example
functionF :: Char -> Char
functionF c = chr (succ (ord c))
functionG :: Char -> Char
functionG = chr . succ . ord
Using Lists
• A list is an ordered set of values of the same type
• It is enclosed in brackets with each element
separated by a comma
listOfInt :: [Int]
listOfInt = [1,2,3,4]
listOfChar :: [Char]
listOfChar = ['h', 'e', 'l', 'l', 'o']
listOfString :: [ [Char] ]
listOfString = [['o', 'n', 'e'], "two", "three"]
Construction of Lists
• A list can be written as x:xs, where x is the head of the list,
xs is the tail, and : is the cons operator
• Every list is built up recursively using the cons operator
whose type is a -> [a] -> [a]
[] == []
1:[] == [1]
2:[1] == [2, 1]
3:[2,1] == 3:2:1:[] == [3, 2, 1]
• The list concatenation operator is ++ and its type is
[a] -> [a] -> [a]
[1,2] ++ [] ++ [3,4,5] == [1, 2, 3, 4, 5]
• Lists of elements can be denoted by giving a range
[2 .. 8 ]
== [2, 3, 4, 5, 6, 7, 8]
[1, 3 .. 12] == [1, 3, 5, 7, 9, 11]
Pattern Matching Over Lists
• An unstructured variable xs matches any list
• (_:_) matches any non-empty list without binding of list
elements
• (x:xs) matches any non-empty list; however, x is bound
to the head and xs to the tail
• (_:[]) is identical to [_] and matches any list with one
and only one element
• (x1:x2:xs) extracts the first two elements of a list
containing two or more elements, with x1 and x2 bound
to the first two elements and xs bound to the tail
List Comprehension
• A subset of a list can be generated using list comprehension
in a common mathematical set notation
[x | x<-g, even x]
generator guard
(Translated as: x such that x is a member of the list g and x is
even)
• Generate a list of all possible pairs out of two sets
pairs :: [a] -> [b] -> [(a,b)]
pairs xs ys = [(x,y) | x <- xs, y <- ys]
Recursion over Lists
• Example: Sum up the elements of a list
sum :: [Int] -> Int
sum [] = 0
sum (x:xs) = x + sum xs
• Example: Filter a list according to a selection criteria
filter :: (a -> Bool) -> [a] -> [a]
filter p [] = []
filter p (x:xs)
| p x
= x : filter p xs
| otherwise = filter p xs
Note: sum and filter are both predefined functions in Haskell
Some Predefined List Functions
•
•
•
•
•
•
•
•
•
•
•
•
•
(:)
(++)
(!!)
map
filter
head
tail
last
init
length
null
take
drop
::
::
::
::
::
::
::
::
::
::
::
::
::
a -> [a] -> [a]
[a] -> [a] -> [a]
[a] -> Int -> a
(a->b) -> [a] -> [b]
(a -> Bool) -> [a] -> [a]
[a] -> a
[a] -> [a]
[a] -> a
[a] -> [a]
[a] -> Int
[a] -> Bool
Int -> [a] -> [a]
Int -> [a] -> [a]
Algebraic Data Types: Enumeration
• This is the simplest kind of algebraic type
data Color = Red | Green | Blue
data RoomNumber = 102 | 214 | 228
| 233 | 245
assignColor :: RoomNumber -> Color
Algebraic Data Types: Product
• This is used to combine two or more types
type Name
type Age
= String
= Int
data People = Person Name Age
• Person is referred to as the constructor of type People. Its
type is Name -> Age -> People
• Person is a function that generates an element of type
People out of the types Name and Age
Algebraic Data Types: Alternatives
• This is used to combine two or more types but allows some
choices
type Name
data Year
data Dept
= String
= Freshman | Sophomore |
Junior | Senior
= Bus | Eng | LA | Math
data People = Student Name Year |
Staffer Name Dept
Algebraic Data Types: Recursive
• A recursive type can be created from an alternative type
data Tree = Nil | Node Int Tree Tree
myTree :: Tree
myTree = Node 1 (Node 2 (Node 4 Nil Nil)
(Node 5 Nil Nil)) (Node 3 Nil Nil)
depth :: Tree -> Int
depth Nil
= 0
depth (Node _ t1 t2) = 1 + max (depth t1)
(depth t2)
Instances of Classes
• When creating a new algebraic type, you may need to inherit
operations from other type classes. This is done using the
deriving keyword
data Color = Red | Green | Blue
deriving (Eq, Ord, Enum, Show, Read)
Example of an Abstract Data Type
Module Stack (Stack, isEmpty, push, pop) where
data Stack a = Empty | MyStack a (Stack a)
isEmpty :: Stack a -> Bool
isEmpty Empty
= True
isEmpty (MyStack _ _) = False
push :: a -> Stack a -> Stack a
push element aStack = MyStack element aStack
pop :: Stack a -> (a, Stack a)
pop Empty
= error "Empty stack"
pop (MyStack element aStack) =
(element, aStack)