Függvények definiálása

Haskell programok

Egy Haskell program deklarációk halmaza.
Deklarációk:

További deklarációk:

A deklarációk sorrendje nem számít!

Modulok

A definíciókat modulokba rendezzük, a modul a fordítási egység.

Egy Haskell modul szerkezete:

Minden Haskell modul egy szövegfájl .hs vagy .lhs kiterjesztéssel.


Készítsünk egy üres X.hs szövegfájlt!

Modul betöltése az értelmezőbe:

:l X.hs

Modul újratöltése:

:r

A definíciókat egy vagy több szöveges fájlba kell leírnunk, ezeket moduloknak nevezzük. A modulnevek betűkből és számokból állnak és nagybetűvel kezdődnek: Char, List, Ratio.

Windowson a .hs kiterjesztésű fájlra kattintva a GHCi automatikusan elindul és betölti a modult.

A modul betöltése után a GHCi értelmező promptjában a Main*>-ban a * azt jelzi, hogy a parancssorban látszanak a modulbeli definíciók és az összes importált modul definíciói (tehát a Prelude is, mert az automatikusan importált).

Megjegyzések

Egysoros megjegyzés:

 -- megjegyzés a sor végéig

Többsoros megjegyzések:

{- megjegyzés -}
{- egymásba 
 {- ágyazott -} 
  megjegyzések -}

Az egysoros megjegyzések a -- jelekkel kezdődnek, és a sor végéig tartanak.

A többsoros megjegyzéseket a {- és -} jelek határolják. A többsoros megjegyzések egymásba ágyazhatók.

Függvények definiálása

Egyparaméteres függvény, típus nélkül:

f x = x + 1

Kérdezzük meg, milyen típust vezetett le a fordító:

Test>

Kétparaméteres függvény, típussal:

g :: Integer -> Integer -> Integer
g a b = a * b + 1

Használat:

Test>
3 :: Integer

A függvény- és változónevek betűkből és számokból állhatnak és kisbetűvel kell kezdődniük. Tartalmazhatják az aláhúzás és az egyszeres idézőjel karaktereket is: f_1, f', f''.

Feladat: Hegy [*]

Generáljuk a következő listát: [1, 2, …, n-1, n, n-1, …, 2, 1]!

mountain :: Integer -> [Integer]

Test>
[1, 2, 3, 2, 1] :: [Integer]
Test>
[1] :: [Integer]
Test>
[] :: [Integer]
Test>
[] :: [Integer]

Feladat: Háromszög szerkeszthetősége

Döntsük el az a, b és c számokról, hogy lehetnek-e egy háromszög oldalhosszai!

areTriangleSides :: Real a => a -> a -> a -> Bool

Test>
True :: Bool
Test>
False :: Bool

Feladat: Prelude.even [*]

Definiáljuk újra a Prelude-beli even függvényt, amely eldönti egy számról, hogy páros-e!

even :: Integer -> Bool

Test>
False :: Bool
Test>
True :: Bool

Mivel a Prelude-ben már definiált az even, ezért úgy definiálhatjuk újra hogy a Prelude-beli definícióját elrejtjük:

Az import deklarációk csak a modul elején lehetnek!

A hiding kulcsszó alkalmazásával több definíciót is elrejthetünk:

Feladat: Prelude.odd

Definiáljuk újra a Prelude-beli odd függvényt, amely eldönti egy számról, hogy páratlan-e!

odd :: Integer -> Bool

Test>
True :: Bool
Test>
[True, False, True, False, True] :: [Bool]

Feladat: Oszthatóság [*]

Definiáljuk az oszthatóságot!

divides :: Integer -> Integer -> Bool

Test>
True :: Bool
Test>
False :: Bool

Feladat: Szökőévek

Állapítsuk meg egy évről, hogy szökőév-e!

isLeapYear :: Integer -> Bool

Test>
[1952, 1956, 1960] :: [Integer]
Test>
False :: Bool
Test>
True :: Bool

Feladat: Négyzetösszeg

Adjuk meg az 1, 2, …, n számok négyzetösszegét!

sumSquaresTo :: Integer -> Integer

Test>
0 :: Integer
Test>
30 :: Integer
Test>
0 :: Integer

Feladat: Osztók [*]

Definiáljunk egy függvényt, amely egy listában előállítja egy szám osztóit!

divisors :: Integer -> [Integer]

Test>
[1, 2, 3, 4, 6, 12] :: [Integer]

Feladat: Valódi osztók

Definiáljunk egy függvényt, amely egy listában előállítja egy szám valódi osztóit!

properDivisors :: Integer -> [Integer]

Test>
[2, 3, 4, 6] :: [Integer]

Operátorok definiálása

(.*.) :: Double -> Double -> Double
a .*. b = a * b + 1

Operátor kötésének és kötési erősségének beállítása az infix, infixl, infixr kulcsszavakkal:

infixl 7 .*.

Már definiált operátor kötési erősségének lekérdezése:

Main*> :i (+)
infixl 6 + 

Az operátornevek nem ASCII szimbólumokból és a következő ASCII szimbólumokból állnak: !?.#$%@&*+-~^/|\<=>: Kivételt képeznek az alábbi kulcsszavak, amelyek nem operátornevek: =, .., |, <-, ->, =>, ::, \, @, ~. (Ezek az utolsó három kivételével már ismerősek.)

Az operátorokat infix módon használjuk, azaz a két operandus közé írjuk az operátor nevét.

Az infix n o deklaráció hatására az o operátor nemkötő lesz n erősséggel. Az erősség 0 és 9 között változhat. infixl balra kötő, infixr jobbra kötő operátort eredményez.