2.14. Haskell

Haskell er et funktionsorienteret programmeringssprog og minder på mange måder om SML. Mange af de ting der er beskrevet i afsnittet om SML gælder derfor også for Haskell. Der er typepolymorfi, højereordens funktioner og funktionsdefinition ved mønstre.

Den første måde hvor Haskell adskiller sig fra SML er at Haskell er et rent funktionsorienteret sprog, hvor SML har nogle imperative dele. Det har især betydning for I/O der i Haskell foregår ved hjælp af et koncept der hedder monader.

Den anden forskel er at Haskell er et dovent sprog. Dette betyder at argumenter til funktioner først bliver evalueret når den kaldte funktion benytter dem. Dette giver blandt andet mulighed for at behandle uendelige datastrukturer, for eksempel uendelige lister af tal.

Der er oversættere og fortolkere til de fleste platforme herunder *BSD, Linux, MacOS og Windows.

2.14.1. Brug af Haskell

Skal man lege med Haskell bør man tage fat i Hugs. Den implementerer en læs-beregn-udskriv løkke hvor man kan skrive et udtryk og få Hugs til at beregne udtrykket. Man kan dog ikke definere nye funktioner, de skal skrives i filer.

Hvis man for eksempel har en fil Test.hs med følgende indhold


mylength :: [t] -> Int
mylength []      = 0
mylength (x:xs)  = 1 + length xs

mysum    :: [Int] -> Int
mysum []         = 0
mysum (x:xs)     = x + sum xs
En session med Hugs kan så se således ud

__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2002
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Report bugs to: hugs-bugs@haskell.org
||   || Version: November 2002  _________________________________________

Haskell 98 mode: Restart with command line option -98 to enable extensions

Reading file "/usr/lib/hugs/lib/Prelude.hs":
                   
Hugs session for:
/usr/lib/hugs/lib/Prelude.hs
Type :? for help
Prelude> :load Test.hs 
Reading file "Test.hs":
                   
Hugs session for:
/usr/lib/hugs/lib/Prelude.hs
Test.hs
Main> mylength [3, 6, 2, 5]
4
Main> mysum [3, 6, 2, 5]
16
Main> 
Man kan så inde fra Hugs redigere Test.hs med kommandoen :edit Test.hs der starter en editor og efterfølgende genindlæser filen

2.14.2. Doven evaluering

Haskell er et dovent sprog. Det betyder at den udsætter beregningen af et udtryk så lang tid som det overhovedet er muligt. Normalt er man vant til at argumenterne i et funktionskald bliver beregnet før funktionen kaldes. Sådan gør haskell ikke.

Man ville for eksempel forvente at følgende stykke kode gik i uendelig løkke:


foo :: Int -> Int
foo 0 = 1
foo n = foo(n+1) + foo(n-1)

switch :: Bool -> t -> t -> t
switch True n m  = n
switch False n m = m

switch True (foo 0) (foo 5)
Men eftersom værdien af (foo 5) bare bliver smidt vil Haskell ikke forsøge at beregne det.

Dette giver mulighed for at definere strukturer der egentligt er uendelige. For eksempel kan Fibonaccis talfølge kan let skrives som:


zip :: [a] -> [b] -> [(a,b)]
zip []     _      = []
zip _      []     = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys

add :: (Int,Int) -> Int
add a b = a + b

fib = 0 : 1 : map add (zip fib, (tail fib))

zip tager to lister og danner en liste af par og add tager et par af to tal og lægger dem sammn.

(zip fib, (tail fib)) laver en uendelig liste af par med to på hinanden følgende tal i Fibonaccis talfølge. map add (...) lægger disse par sammen.