CS118 Programming LanguagesLecture 17 (Doug McIlroy)Contents
Assignmentsome Haskell exerciseHaskell SummaryHaskell is like ML in many ways
Different in modest ways
And profoundly different in others
Typical function declarations
ML head : 'a list -> 'a;
fun head (x::_) = x;
Hs head :: [a] -> a
head (x:xs) = x
ML fact : int -> int
fun fact 0 = 1
| fact n = n*(fact (n-1))
Hs fact :: Int -> Int
fact 0 = 1
fact n = n*(fact (n-1))
Note: types begin with upper case letter by convention
ML datatype ('a,'b) pair = Pair of 'a*'b;
Hs data Pair a b = Pair a b
Alternative, might have written any of the following with different meanings
data Pair a b = Pair a b data Pair a b = Pair (a, b) data Pair a b = Pair [a] [b]
ML datatype 'a tree = Empty | Tree of ('a tree, 'a, 'a tree);
Hs data Tree a = Empty | Tree (Tree a) a (Tree a)
ML fun map _ [] = []
| map f (x::xs) = f x :: map f xs;
Hs(1) map _ [] = []
map f (x:xs) = f x : map f xs
Hs(2) map f xs = [f x | x<-xs] -- like set comprehension: {f x | x \(mo xs}
ML fun cross [] _ = [] -- cross [1,2] [3,4] = [(1,3),(1,4),(2,3),(2,4)]
| cross _ [] = []
| cross xs ys = map (fn(x)=>map (fn(y)=>(x,y)) ys) xs;
Hs cross [] _ = []
cross _ [] = []
cross xs ys = [(x,y) | x<-xs, y<-ys]
Hs zip [] _ = []
zip _ [] = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys
zipWith _ [] _ = []
zipWith _ _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
Haskell specials zeroes = 0 : zeroes -- infinite sequence of zeroes ints = [1..] powersof2 = [2^x | x<-ints] Type classes and overloading Eq -- things that can be compared for equality Ord -- things that can be compared for order Num -- operands of + - * negate ... Fractional -- operands of / recip ... (+) :: Num a => a -> a -> a -- + applies to 2 things of the same type in class Num Power series represented as a list of coefficients
instance Num a => Num [a] where -- if type a is in class Num then lists of a are in Num
_ + [] = []
[] + _ = []
(x:xs) + (y:ys) = x+y : xs+ys
-- xs + ys = zipWith (+) (xs++zeroes) (ys++zeroes) -- one-line form
negate xs = [-x | x<-xs]
_ * [] = []
[] * _ = []
(x:xs) * ys@(y:yt) = x*y : [x]*yt + xs*ys
fromInteger c = [c] -- coerce any Integer type to power series over that type
instance Fractional a => Fractional [a] where
...
integral [] = []
integral xs = 0 : zipWith (\x y->x*(recip y)) xs [1..]
expx = 1 + integral expx
cosx = 1 - integral sinx
sinx = integral cosx
For more information:
http://www.haskell.org
Generating regular expression languages
-- FILE: enum_re.hs
-- PURPOSE: Enumerate the strings for a regular expression,
-- ordered by length and lexicographically within length.
-- enum "a(b|c)|d" == ["d","ab","ac"]
-- enum "(b|ab*a)*" == ["","b","aa","bb","aab","aba","baa","bbb",...
type Lang = [String]
cmp :: String -> String -> Ordering
enum :: String -> Lang
alt, cat :: Lang -> Lang -> Lang
clo :: Lang -> Lang
cmp x y = compare (length x, x) (length y, y)
enum s = parse [] s
alt [] ys = ys -- alternation (merge languages)
alt xs [] = xs
alt xs@(x:xt) ys@(y:yt) = case cmp x y of
LT -> x : alt xt ys
EQ -> x : alt xt yt
GT -> y : alt xs yt
cat [] _ = [] -- catenation (cross product of languages)
cat _ [] = []
cat (x:xt) ys@(y:yt) =
(x++y) : alt (cat [x] yt) (cat xt ys)
clo [] = [""] -- Kleene closure
clo ("":xs) = clo xs
clo xs = "" : cat xs (clo xs)
Parsing regular expressions
-- FILE: parse_re.hs
-- PURPOSE: parse regular expressions
-- MODS: 2002.05.21 -- original -- MD McIlroy
-- shift-reduce parser; stack symbol holds its language
data Syntax = P Lang -- Primary ::= letter | "()" | "(" A ")"
| C Lang -- Catenation ::= P | P "*" | C C
| A Lang -- Alternation ::= C | A "|" A
| L -- "("
type Stack = [Syntax]
parse :: Stack -> String -> Lang
parse (P(x):z) ('*':s) = parse (C(clo x):z) s
parse (P(x):z) s = parse (C(x):z) s
parse (C(y):C(x):z) s = parse (C(cat x y):z) s
parse (C(x):z) ('|':s) = parse (A(x):z) s
parse (C(x):z) (')':s) = parse (A(x):z) (')':s)
parse (C(x):z) "" = parse (A(x):z) ""
parse (A(y):A(x):z) s = parse (A(alt x y):z) s
parse (A(x):L:z) (')':s) = parse (P(x):z) s
parse (L:z) (')':s) = parse (P([""]):z) s
parse z ('(':s) = parse (L:z) s
parse z (c:s) | isAlpha c = parse (P[[c]]:z) s
| otherwise = error ("syntax at "++(c:s))
parse [A(x)] "" = x
parse _ "" = error "unexpected end"
|