Haskell. Kjetil Ørbekk. Programvareverkstedet, 19. mars 2009

Like dokumenter
INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

TDT4165 PROGRAMMING LANGUAGES. Exercise 01 Introduksjon til Oz

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

Høyere-ordens prosedyrer

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering. En metasirkulær evaluator, del 2

INF2810: Funksjonell Programmering. En metasirkulær evaluator, del 2

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

Typer. 1 Type: boolean. 2 Verdimengde: {true, false} 3 Operatorer: NOT, AND, OR... 1/19. Forelesning Forelesning

INF2810: Funksjonell Programmering

Variable Man kan bruke variable i ML. ML (kap 5 og 6) Nye datatyper INF3110/4110 INF3110/4110 INF3110/4110 INF3110/4110. Variable i ML.

INF2810: Funksjonell Programmering

Rekursjon og lister. Stephan Oepen & Erik Velldal. 1. februar, Universitetet i Oslo

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

Vi skal se på lambda-uttrykk. Følgende er definerte og vil bli brukt gjennom oppgaven

Lynkurs i shellprogrammering under Linux

Beskrivelse av programmeringsspråket Compila15 INF Kompilatorteknikk Våren 2015

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

Dagens tema Innføring i ML - del IV

Del 1 En oversikt over C-programmering

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

INF2810: Funksjonell Programmering. Kommentarer til prøveeksamen

INF2810: Funksjonell Programmering. Mer om strømmer

ML (kap 5 og 6) INF3110/4110. Variable i ML. Nye datatyper. Currying. Avanserte listeoperatorer. Typeanalyse

INF1010 våren januar. Objektorientering i Java

Introduksjon til objektorientert. programmering. Hva skjedde ~1967? Lokale (og globale) helter. Grunnkurs i objektorientert.

UNIVERSITETET I OSLO

INF2810: Funksjonell Programmering. Strømmer og utsatt evaluering

Plan: Parameter-overføring Alias Typer (Ghezzi&Jazayeri kap.3 frem til 3.3.1) IN 211 Programmeringsspråk

Eksamen i emne TDT4165 / SIF8028 Programmeringsspråk

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

Kapittel 1 En oversikt over C-språket

IN1010 våren januar. Objektorientering i Java

Kapittel 8: Programutvikling

Forkurs INF1010. Dag 1. Andreas Færøvig Olsen Tuva Kristine Thoresen

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

INF2810: Funksjonell Programmering. Muterbare data

Betinget eksekvering og logiske tester i shell

Fra Python til Java. En introduksjon til programmeringsspråkenes verden. Dag Langmyhr

Programmering i C++ Løsningsforslag Eksamen høsten 2005

INF2810: Funksjonell Programmering. Lokale variabler. Og trær.

INF2810: Funksjonell Programmering. En metasirkulær evaluator

INF2810: Funksjonell Programmering. En metasirkulær evaluator

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

INF2810: Funksjonell Programmering. Køer, tabeller, og (litt om) parallelitet

TDT4165 PROGRAMMING LANGUAGES. Exercise 02 Togvogn-skifting

AlgDat - Øvingsforelesning 1 Introduksjon til Python, lenkede lister og øving 1

INF2810: Funksjonell Programmering. Mer om verditilordning. Tabeller. Og strømmer.

Prosedyrer. Lars Vidar Magnusson. October 26, Lars Vidar Magnusson () Forelesning i DAS October 26, / 19

Lisp 2: Lister og funksjoner

INF januar 2015 Stein Michael Storleer (michael) Lenkelister

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

IN1140, H2018 gruppetime oppgaver Introduksjon til Tekst i Python

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

Programmeringsspråk for nybegynnere. Krav til språket. Krav til språket. Krav til språket

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

INF2810: Funksjonell Programmering. Mer om verditilordning. Tabeller. Og strømmer.

INF2100. Oppgaver 26. september til 1. oktober 2007

INF2810: Funksjonell Programmering

Sideeekter og makroer i Lisp

UNIVERSITETET I OSLO

INF2810: Funksjonell Programmering. Eksamensforberedelser

INF2810: Funksjonell programmering: Mer om Scheme. Rekursjon og iterasjon.

Eksamen i emnet INF100 Grunnkurs i programmering (Programmering I) og i emnet INF100-F Objektorientert programmering i Java I Løsningsforslag

Finne ut om en løsning er helt riktig og korrigere ved behov

Transkript:

Haskell Kjetil Ørbekk Programvareverkstedet, 19. mars 2009

Imperativ programmering Tilstand Operasjoner function uppercase(list) { x = 1 } while (x < length(list)) { uppercase(list[x]) x = x + 1 }

Funksjonell programmering Verdier Funksjoner Transformasjon uppercase list = map toupper list

Haskell Haskell 98 Et rent funksjonelt programmeringsspråk Statisk og implisitt typesystem Lat evaluering

Funksjonell programmering f x -- lik for lik x x = 1 x = x + 1 «Sett variablene dine riktige første gangen, så slipper du å endre dem!»

Litt syntaks -- Kommentar, eller: {- Kommentar -} -- En funksjon: f x = 2 * x -- Vi evaluerer den: > f 10 20 -- Mer avansert: g x y = x*3 + y^2 > g 2 3 15

Layout funksjon x y z = do { foobar; blaz; boo; } where { foobar = blaff x; blaz = boo x; boo = z foobar; } funksjon x y z = do foobar blaz boo where foobar = blaff x blaz = boo x boo = z foobar

GHC http://www.haskell.org/ghc/ aptitude install ghc

Noen funksjoner max x y = if x > y then x else y > max 4 1 4 x ~> y = max x y > 4 ~> 1 4 min x y x < y = x otherwise = y x <~##! y = min x y > 4 <~##! 1 1

Lister (omg ) Mest (mis)brukte datastrukturen i FP xs = [1, 2, 3] ys = [ en liten katt, 200 ekorn, fire marsvintonn ] -- Eller: zs = [(1, liten katt ), (200, ekorn ), (4, marsvintonn )]

Flere lister xs = [1, 2] -- er sukker for: xs = 1 : 2 : [] -- les: 1 conset på 2 conset på tom liste -- -- Altså (i pseudo-haskell): data [a] = [ ] a : [a]

xs = [ 1, 2, 3, 4, 5 ]

Eksempler xs = [1, 2, 3, 4, 5] > head xs => 1 > tail xs => [2, 3, 4, 5]

Lister til hygge og moro -- null: er denne lista tom lr?? null [] == True null [1,2,3] == False -- nå kan vi lage hva vi vil: length xs = if null xs then 0 -- tom liste else 1 + length (tail xs) -- recurshun! -- og en operator: xs!! n = if n == 0 then head xs else tail xs!! (n-1)

Pattern matching -- Constructors data Bool = True False -- Pattern matching: not True = False not False = True True && True = True _ && _ = False True _ False x = True = x

Listekos v. 2.0 --...med pattern matching på lister. -- -- Constructors: data [a] = [ ] a : [a] -- Med variabler for a og [a]: liste = [] -- eller liste = x : xs -- null: er denne lista tom lr?? null [] = True null (x:xs) = False

Listekos, 1.0 vs. 2.0 length [] = 0 length (x:xs) = 1 + length xs (x:xs)!! 0 = 0 (x:xs)!! n = xs!! (n-1) length xs = if null xs then 0 else 1 + length (tail xs) xs!! n = if n == 0 then head xs else tail xs!! (n-1)

Funksjoner vs. operatorer -- -- I Haskell: operatorer er _ikke_ spesielle. -- > mod 5 2 -- kjent som 5 % 2 i andre språk. > 5 `mod` 2 > (`mod` 2) 5 > (2 `mod`) 5 2 1 + 2 (+) 1 2 (1+) 2 (+2) 1

List comprehensions -- Doble alle elementer i en liste: xs = [1..10] ys = [ x * 2 x <- xs ] > ys [2, 4.. 20] -- Finne alle oddetall i en liste: ys = [ y y <- xs, odd y ] > ys [1, 3.. 10]

Hva er dette? funky [] = [] funky (x:xs) = funky a ++ [x] ++ funky b where a = [y y <- xs, y < x] b = [z z <- xs, z >= x] ( ) til hjelp [1, 2, 3] ++ [4, 5, 6] => [1, 2, 3, 4, 5, 6]

Oppgave Skriv en funksjon drop n som fjerner de n første elementene av en liste: drop 3 [1, 2, 3, 4] => [4] -- Til hjelp: take n take _ [] = [] take 0 [] = [] take n (x:xs) = x : take (n-1) xs -- Dette er en god start: drop _ [] = <???> drop 0 xs = <???> drop n (x:xs) = <???>

Typer

Alt har en type x :: Int x = 1 a :: [Int] a = [1,2,3] b :: [[Int]] b = [[1,2], [7,8]] c :: [(Int, String)] c = [(10, egg ), (5, datamaskiner )]

Ja, alt! f :: Int -> Int f x = 2 * x length :: [a] -> Int length [] = 0 length (x:xs) = 1 + length xs drop :: Int -> [a] -> [a] drop _ [] = [] drop 0 xs = xs drop n (x:xs) = drop (n-1) xs

«Tips: Bruk :t i ghci for å spørre etter typen til et uttrykk. Eks: :t drop»

Hva er typen til (==)? -- Hvis vi gir den argumenter: :t x == y => Bool -- Uten argumenter: :t (==) => (a -> a -> Bool)?

Typeklasser class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x /= y = not (x == y) data Babl = Abl Fabl > Abl == Abl error: No instance for (Eq Babl). instance Eq Babl where Abl == Abl = True Fabl == Fabl = True _ == _ = True > Abl == Fabl False

Demo :t

($) ($) :: (a -> b) -> a -> b f $ x = f x infixr 0 $ map (+1) map (*2) [1,2,3] == (map (+1) map) (*2) [1,2,3] map (+1) $ map (*2) [1,2,3] == map (+1) (map (*2) [1,2,3])

Funksjonskomposisjon (.) :: (b -> c) -> (a -> b) -> (a -> c) (f. g) x = f (g x) > sqrt (-2) NaN > (sqrt. abs) (-2) 1.4142...

map f :: Int -> Int f = x * 2 map :: (a -> b) -> [a] -> [b] map f :: [Int] -> [Int] > map f [1..3] :: [Int] [f 1, f 2, f 3] -- == [ 2, 4, 6] map f [] = [] map f (x:xs) = f x : map f xs > tolower 'A' 'a' > map tolower JG VILHA KAKE jg vilha kake > map (`mod` 3) [0..] [0,1,2,0,1,2,0,1,2,...]

λ -- Lambda: funksjoner uten navn > (λx -> x * 2) 2 4 -- Til map: map (\x -> x / 2) [1..10] > [0.5, 1.0, 1.5,.. 10] -- Men vanligere: map (/2) [1..10] > (\x y z -> x^2 + y + z * 2)

Filter filter :: (a -> Bool) -> [a] -> [a] filter _ [] = [] filter predikat (x:xs) = case predikat x of True -> x : filter predikat xs False -> filter predikat xs -- eller filter _ [] = [] filter predikat (x:xs) predikat x = x : filter predikat xs otherwise = filter predikat xs

Eksempel -- List comprehension: xs = [1..10] ys = [ y * 2 y <- xs, odd y ] -- Map og filter: ys = map (*2) $ filter odd $ xs qsort :: (Ord a) => [a] -> [a] qsort [] = [] qsort (x:xs) = qsort smaller ++ [x] ++ qsort larger where smaller = filter (< x) xs larger = filter (>=x) xs

Fold foldr :: (a -> b -> b) -> b -> [a] -> b foldr f x [] = x foldr f k (x:xs) = f x (foldr f k xs) -- == f x $ foldr f xs, remember? foldr (+) 0 [1,2,3] = (+) 1 (foldr (+) 0 [2,3]) = (+) 1 ((+) 2 (foldr 0 [3])) = (+) 1 ((+) 2 ((+) 3 (foldr 0 []))) = (+) 1 ((+) 2 ((+) 3 0)) = (+) 1 ((+) 2 3) = (+) 1 5 = 6

Mer folding sum, product :: (Num a) => [a] -> a sum xs = foldr (+) 0 xs pruduct xs = foldr (*) 1 xs map :: (a -> b) -> [a] -> [b] map f xs = foldr (\x xs -> f x : xs) [] xs concat :: [[a]] -> [a] concat xss = foldr (++) [] xss length :: [a] -> Int length xs = foldr (\x n -> 1 + n) 0 xs

Eksempel: insertion sort -- Hjelpefunksjon insert :: (Ord a) => a -> [a] -> [a] insert e [] = [e] insert e (x:xs) x < e = x : insert e xs otherwise = e : (x:xs) isort :: (Ord a) => [a] -> [a] isort xs = foldr insert [] xs

foldl Tail recursive. http://www.haskell.org/haskellwiki/fold

Oppgaver Definer filter med foldr. takewhile er gitt nedenfor. Kan du skrive den med en foldr og en hjelpefunksjon? takewhile _ [] = [] takewhile p (x:xs) p x = x : takewhile p xs otherwise = []

Monads

Monad -- Monad: data m a = [...] -- Består av: -- return x; pakker inn x i monaden return :: a -> m a -- En funksjon som binder sammen (>>=) :: m a -> (a -> m b) -> m b

Maybe data Maybe a = Just a Nothing data Person = Person { mor :: Maybe Person, far :: Maybe Person, navn :: String } mor :: Person -> Maybe Person far :: Person -> Maybe Person navn :: String

Grandparents mormor :: Person -> Maybe Person mormor p = case mor p of Nothing -> Nothing Just m -> mor m farmormor :: Person -> Maybe Person farmormor p = case mor p of Nothing -> Nothing Just m -> case mor m of Nothing -> Nothing Just m' -> far m' --...idioti!

Maybe Monad data Maybe a = Just a Nothing -- husk data m a =..., m = Maybe return :: a -> Maybe a -- a -> m a return x = Just x (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b -- m a -> (a -> m b) -> m b Nothing >>= _ Just x >>= f = Nothing = f x -- Vi skriver farmormor på nytt: farmormor p = p >>= mor >>= mor >>= far -- Velkommen til Monads!

IO, en Monad -- -- IO: Spesielt og innebygd (no shit) -- data IO a =... return :: a -> IO a return x =... (>>=) :: IO a -> (a -> IO b) -> IO b i >>= f =...

Hello, World! -- IO er da ikke så vanskelig? :-) main :: IO () main = putstrln Hello, World! (>>=) :: IO a -> (a -> IO b) -> IO b putstrln :: String -> IO () getstrln :: IO String getline >>= putstrln -- cat?

Eksempel: wc -- words en liten\ntest => [ en, liten, test ] getcontents :: IO String -- leser hele stdin words :: String -> [String] length :: [a] -> Int show :: (Show a) => a -> String putstrln :: String -> IO () -- Gitt en string: main = getcontents >>= \content -> putstrln $ show $ length $ words content -- eller main = getcontents >>= putstrln. show. length. words

do main = getcontents >>= \content -> let nwords = length (words content) in putstrln $ show nwords -- vs main = do content <- getcontents let nwords = length (words content) putstrln (show nwords)

Fra fil import System.IO wc :: IO String -> IO Int wc reader = do content <- reader let nwords = length (words content) return nwords -- readfile :: String -> IO String -- getargs :: IO [String] main :: IO () main = do args <- getargs wordcount <- if null args then wc getcontents else wc (readfile $ head args) putstrln (show wordcount)

Mer om Monads Monads: Mer enn bare IO State Monad Sjekk All About Monads : http://www.haskell.org/all_about_monads/

Mer Haskell Lat evaluering Currying Debugging Extensions Parallellitet Haskell FFI Profiling

Ressurser Real World Haskell http://www.realworldhaskell.org/ Learn You A Haskell http://learnyouahaskell.com/ #haskell på freenode Hoogle - API-søking http://www.haskell.org/hoogle/