Visualisere

torsdag 31. desember 2009 18:15

Haskell i all enkelhet

 

For denne artikkelen går vi ut ifra at du har installert en fungerende Haskell implementasjon med interaktiv sessions. Hvordan du gjør dette kan du lese om her.

Aritmetikk:

Ikke uventet kan vi gjøre aritmetiske operasjoner med Haskell. Skriv inn et gyldig aritmetisk uttrykk og trykk enter.

 

Hugs> 1+2+3
6 :: Integer

Hugs> sqrt 2
1.4142135623731 :: Double

Hugs> pi
3.14159265358979 :: Double

Hugs> 10/0
1.#INF :: Double


Vi ser i eksempelene over at Haskell Interpreteren gir oss svaret, samt hvilken type den har interferensert svaret til. Mer om typer og inferens senere.

 

Par, tripletter, tupler:

Paranteser brukes for å gruppere verdier av samme type. To verdier er et par, tre er en triplett, og n verdier er en n-tuple.

Hugs> (0,0)
(0,0) :: (Integer,Integer)

 

Par med Integers.

Hugs> ('a','b')
('a','b') :: (Char,Char)

 

Par med Characters, merk ''.

Hugs> ("ab","cd")
("ab","cd") :: ([Char],[Char])

 

Par med Characterlister, d.v.s streng, merk "".

Hugs> ('a','b', 'c', 'd')
('a','b','c','d') :: (Char,Char,Char,Char)

 

En tuple med Characters, merk ''.

Vi ser noen tupler og hvordan Haskell Interpreteren interferer typene. Vi kan ha alle gyldige typer i en tupel.

Vi har noen innebygde funksjoner som virker på par. fst (first) og snd (second). Merk at verdiene i et par ikke trenger å være av samme type. Dette gjelder alle tupler.

Hugs> fst (0, 1)
0 :: Integer
Hugs> snd (0,1)
1 :: Integer
Hugs> fst ("string", 0)
"string" :: [Char]
snd (0, 'a')
'a' :: Char

Dersom du prøver disse funksjonene på annet en par vil du få en feilmelding fra Interpreteren.

 

Oppgave: Skriv en funksjon som returnerer 4 fra tuplet: (('a',4),"string")?

Løsning:

Hugs> snd (fst(('a',4),"string"))

4 :: Integer

 

Lister:

I motsetning til par, tripletter og tupler kan lister inneholde et ubegrenset antall elementer. Men lister krever derimot at alle elementer i listen er av samme type.

Hugs> [0,1,2,3]
[0,1,2,3] :: [Integer]

 

Liste med Integers.

Hugs> ['a','b','c','d']
"abcd" :: [Char]

 

Liste med Characters. D.v.s en streng.

Hugs> ["ab","cd","ef","gh"]
["ab","cd","ef","gh"] :: [[Char]]

 

Liste med strenger.

Hugs> []
[] :: [a]

 

Den tomme listen.

Lister defineres ved hjelp av [ ] (eng:square brackets). Tupler ble definert ved hjelp av ( ) (eng:paranthesis).

 

Vi konstruerer lister ved hjelp av operatoren con / : (tenk: construct) og den tomme listen.

Hugs> 'a' : 'b' : 'c' : []
"abc" :: [Char]
Hugs> 1 : 2 : 3 :
[1,2,3] :: [Integer]
Hugs> True : False : []
[True,False] :: [Bool]
Hugs> [] : []
[[]] :: [[a]]

Noen definerte funksjoner på lister.

Hugs> length [1,2,3]
3 :: Int
Hugs> head[1,2,3]
1 :: Integer
Hugs> tail[1,2,3]
[2,3] :: [Integer]

Length: Returnerer lengden på listen. D.v.s antall elementer som er i listen.

Head: Returnerer første elementet i listen.

Tail: Returnerer alt utenom første elementet i listen.

 

Som nevnt lenger oppe er en streng i Haskell en liste med karakterer.

Hugs> ['h','e','i']
"hei" :: [Char]
Hugs> 'h':'e':'i':[]
"hei" :: [Char]

Vi konkatinerer (setter sammen) lister med ++ operatoren.

Hugs> "Hei " ++ "verden"
"Hei verden" :: [Char]

Konverter string til numeriske verdier.

read "1" + 2
3 :: Integer
Hugs> read "1" + read "2"
3 :: Integer

Konverter numeriske verdier til string.

Hugs> "en plus to er lik " ++ show 3
"en plus to er lik 3" :: [Char]

 

Bruk en funksjon på alle elementer v.h.a listefunksjonen map. Map tar inn en funksjon, samt en liste med verdier og anvender den gitte funksjonen på alle elementer i listen. Merk at når vi mapper over en liste vil lengden på innlisten og utlisten være like. Vi endrer kun selve elementene i listen.

Char> map toUpper "hei verden"
"HEI VERDEN" :: [Char]
Char> map toLower "Hei Verden"
"hei verden" :: [Char]

Om du bruker en standard WinHugs implementasjon er det mulig du må laste modulen Char for å få tilgang til toUpper / toLower.

Char> :load Char

Hugs session for:
file:{Hugs}\packages\hugsbase\Hugs\Prelude.hs
file:{Hugs}\packages\base\Prelude.hs
file:{Hugs}\packages\hugsbase\Hugs.hs
file:{Hugs}\packages\hugsbase\Hugs\Char.hs
file:{Hugs}\packages\base\Data\Char.hs
file:{Hugs}\packages\haskell98\Char.hs
Char>

Vi kan filtrere ut elementer i en liste ved å bruke listefunksjonen filter.

Char> filter isUpper "FJERN meg"
"FJERN" :: [Char]
Char> filter isLower "FJERN meg"
"meg" :: [Char]

Vi kan gjøre operasjoner mellom alle elementene i en liste ved å bruke listefunksjonen foldr / foldl. Denne funksjonen tar tre argumenter: en funksjon, en start verdi og en liste.

foldr (+) 0 [1, 2, 3]
6 :: Integer

 

0+(1+2+3 )= 6.

foldr (*) 1 [1, 2, 3]
6 :: Integer

 

1*(1*2*3) = 6

Merk at vi i (*) eksempelet har satt 1 som start verdi istedenfor 0. Dette fordi 0*(1*2*3) blir 0, og dermed ikke det svaret vi er ute etter.

Ved å bruke foldr går vi ut ifra at uttrykket som skal evalueres er høyre assosiativt. Men dette er ikke alltid tilfelle, f.eks ved subtraksjon ( - ).

foldr (-) 1 [4,8,5]
0 :: Integer
foldl (-) 1 [4,8,5]
-16 :: Integer

Vi kan bruke foldl for å assosiere uttrykket mot venstre som vist i eksempelet over.

Merk at foldr evaluerer uttrykket forløpende og kan derfor i teorien brukes på uendelige lister, mens foldl evaluerer v.h.a en rekursiv stabel, og en vil derfor kun få resultat på endelige mengder.

foldr (-) 1 [4,8,5]
==> 4 - (foldr (-) 1 [8,5])
==> 4 - (8 - foldr (-) 1 [5])
==> 4 - (8 - (5 - foldr (-) 1 []))
==> 4 - (8 - (5 - 1))
==> 4 - (8 - 4)
==> 4 - 4
==> 0
foldl (-) 1 [4,8,5]
==> foldl (-) (1 - 4) [8,5]
==> foldl (-) ((1 - 4) - 8) [5]
==> foldl (-) (((1 - 4) - 8) - 5) []
==> ((1 - 4) - 8) - 5
==> ((-3) - 8) - 5
==> (-11) - 5
==> -16

 

Da avslutter vi denne artikkelen her, og gleder oss til neste artikkel kommer. Da skal vi se litt på hvordan vi kan utvide mulighetene våre ved å programmere egne funksjoner, legge de i en ekstern fil som vi laster inn i Interpreteren.

Sist oppdatert søndag 18. juli 2010 22:51
 

Legg til kommentar


Sikkerhetskode
Vis ny kode

Samarbeidspartner

Interaktiv 3D logo

Logg inn


Visualisere