Sei sulla pagina 1di 33

Haskell

Eric Alzheimer

What is Haskell?
Pure Functional Language
Powerful, polymorphic, strong and
strict type system
... with type inference!
Lazily evaluated
mathy syntax with significant
whitespace (like Python)
Emphasizes minimizing side-effects

History
1970s: ML by Robert Milner; Used in
academia
1980s: ML had many (~12) pure,
lazily evaluated descendents
1990: Committee formed to unify
these languages into one creates
Haskell.
Named after logician Haskell Curry

Who uses it?


Originally popular in academia (math
proofs, prog-lang research)
Teaching language
Functional features in popular
dynamic languages (Python, Perl,
Ruby) have increased popularity of
Haskell as a real-word general
purpose language.

Software in Haskell
GHC -> Production quality Haskell
optimizing compiler and interpreter
Pugs -> Perl 6 interpreter (first
one, actually)
Darcs -> Distributed version control
system
Bluespec SystemVerilog ->
Synthesizable hardware description
language.

Language Basics

Functions
Everything is a function
thisIsTwo = 2
sum x y = x + y
foo x y z = z sum x y

>>> foo 1 2 3
--> 0

Data Structures
Collections of data
Can have multiple internal
structures
Can be recursive

Data Structures
data Point = Point Int Int
data Shape = Rect Point Point
| Circle Point Int
data Colors = Red|Green|Blue
type Points = [Point]
myCircle = Circle (Point 2 4) 9

Types?????
All of the functions a few slides
ago are strictly typed
... But we had no type declarations.
This is because Haskell has type
inference.
The compiler/interpreter analyzes
your code and automatically assigns
the most general possible type.
However, it is common to specify the
type of top level declarations, to
ensure correctness and document
functionality

Types!!!!!
myNum :: Int
myNum = 2

myOtherNum :: Float
myOtherNum = 2.0

myFunc :: Int -> Int -> Int


myFunc x y = (2 * x) + x - y

Lists
myList = [1, 2, 3]

(define my-list (1 2 3))

longer = 0 : myList

(cons 0 my-list)

head my-list

(car my-list)

tail my-list

(cdr my-list)

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

(append (1 2) (3 4))

QWER : [2, 3, 4]

[1, 2] :: [Int]

ERROR

Branching
1. Pattern Matching
2. Guards

Pattern Matching
Multiple function definitions
Chosen based on value and structure
of arguments
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
isTwo 2 = True
isTwo _ = False

Structural pattern matches


The constructors for a type are also
their deconstructors, used to get
data out of them.
data Shape = Rect Int Int
| Circle Int
area

(Rect w h)

= w * h

area

(Circle r)

= pi * r * r

width (Rect w _)

= w

width (Circle r)

= 2 * r

Guards
Like cond in Scheme/Lisp
Series of conditional expressions

randomFunction x y
| x <= y
= (x + y) / 2
| (y 2) > 7
= y x
| odd (x + y)
= x + y
| otherwise
= 42

Looping

Recursion
As a functional language, recursion
is the most basic looping construct.

factorial 0 = 1
factorial n = n * factorial (n 1)

High Order Functions


However, explicit recursion is not
good style. High order functions
should be used instead.
factorial x = product [1..x]
sqEv xs = map (\x -> x*x) (filter (\x -> even x) xs)

Local Variables
myFunction a b = x y
where x = a + b
y = a * b
myOtherFunction thing = let a = getFoo thing
b = getBar thing
in a + b

Unusual Features
1. Lazy Evaluation
2. Monadic IO
3. Partial Evaluation

Lazy Evaluation
Values arent evaluated until they
are forced to be evaluated.
In C/Java/Scheme, arguments are
evaluated before call. In Haskell,
they are only evaluated if used.
myIf True x y = x
myIf False x y = y
>>> myIf (2 == 3) [1..] [1, 2]
--> [1, 2]

Monadic IO
Monad --> Abstract type used to
model sequence, state, and side
effects.
Do notation
getName :: IO String
getName = do putStrLn Enter your name:
name <- getLine
if name == then do
putStrLn No name entered...
getName - Try again
else do
return name

Partial Functions
sum :: Int -> Int -> Int
sum x y = x + y
-- sum :: Int -> (Int -> Int)
addFive = sum 5
-- What type?
addFive :: Int -> Int
>>> addFive 3
--> 8

Sample Program
Really simple polynomial
derivative calculator.

*SimpleDeriv> main
Enter a polynomial like "2x^4 + 3x + 7" to get a derivative
Enter "q" to exit
>>> 2x^9 + 3x + 4x^2 + 6
==> 18x^8 + 3 + 8x
>>> 2
==>
>>> q
*SimpleDeriv>

module SimpleDeriv where


-- Import some list utilities from a standard library
import Data.List
-- Define the data structure for a single term
-- It as an algebraic type with two possible forms:
-- either constant or term
data TermInfo = Constant Integer
| Term Integer Integer
deriving (Show, Read, Eq)
-- A polynomial is just a list of terms
type Polynomial = [TermInfo]

-- Take the derivative of a single term


termDerivative :: TermInfo -> TermInfo
termDerivative (Constant value) = Constant 0
termDerivative (Term coef 1)
= Constant coef
termDerivative (Term coef expo) =
Term (coef * expo) (expo - 1)
-- Take the derivative of an entire polynomial
derivative :: Polynomial -> Polynomial
derivative xs = filter nonZero (map termDerivative xs)
where nonZero (Constant 0) = False
nonZero (Term 0 _)
= False
nonZero _
= True

-- Convert a
termToString
termToString
termToString
termToString
termToString
termToString

term to a string
:: TermInfo -> String
(Constant value) = show value
(Term 1 1)
= "x"
(Term 1 expo)
= "x^" ++ (show expo)
(Term coef 1)
= (show coef) ++ "x"
(Term coef expo) =
(show coef) ++ "x^" ++ (show expo)

-- Convert a polynomial to a string


polyToString :: Polynomial -> String
polyToString xs =
intercalate " + " (map termToString xs)

-- Convert a single term into a string


termFromString :: String -> TermInfo
termFromString str
| "x^" `isPrefixOf` str = Term 1 (read (drop 2 str))
| "x^" `isInfixOf` str = let (left, (_:_:right)) = (break foundX str)
foundX c = c == 'x'
coef = read left
expo = read right
in Term coef expo
| "x" `isPrefixOf` str = Term 1 1
| "x" `isInfixOf` str = let coef = read (take ((length str) - 1) str)
in Term coef 1
| otherwise = Constant (read str)
polyFromString :: String -> Polynomial
polyFromString xs = map termFromString (filter notPlus (words xs))
where notPlus x = not (x == "+")

main :: IO ()
main = do
putStrLn "Enter a polynomial like \"2x^4 + 3x + 7\" to get a derivative"
putStrLn "Enter \"q\" to exit"
mainloop

mainloop :: IO ()
mainloop = do
putStr ">>> "
line <- getLine
if line == "q"
then return ()
else do
putStr "==> "
putStrLn (polyToString (derivative (polyFromString line)))
mainloop

Resources
www.haskell.org
Real World
Haskell

End.

quicksort []
= []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where lesser = filter (< p) xs
greater = filter (>= p) xs

Potrebbero piacerti anche