Algebrai adattípusok

Algebrai típusdefiníció egy konstruktorral

Példa:

data IPoint = P Int Int
  deriving (Eq, Ord, Show, Data, Typeable)

Használat

Pont létrehozása:

Test>

Mintaillesztés és konstrukció:

mirrorO :: IPoint -> IPoint
mirrorO (P x y) = P (-x) (-y)

Feladat: Eltolás [*]

translate :: (Int, Int) -> IPoint -> IPoint

Test>
P 3 5 :: IPoint

newtype és data

Tekintsük a következő három definíciót:

-- data    IPoint   = P Int Int
-- data    IPoint'  = P (Int, Int)
-- newtype IPoint'' = P (Int, Int)

IPoint és IPoint'' izomorfak, IPoint' egy kicsit különbözik tőlük. Erről a különbségről később lesz szó.

Több nulla paraméterű konstruktor

data Direction 
     = L 
     | R
        deriving (Eq, Ord, Show, Data, Typeable)

Ezzel definiáljuk

(Konstruktornak nevezzük a mintában is használható függvényt/konstanst.)


L-et és R-t konstruktoroknak nevezzük. A konstruktoroknak és a típusnévnek nagybetűvel kell kezdődniük.

Megkértük a fordítót, hogy automatikusan definiálja:

Feladat: L-ek száma [*]

numOfLs :: [Direction] -> Int
 -- length, filter, (==)

Test>
3 :: Int

Feladat: Irány tükrözése [*]

mirror :: Direction -> Direction
 -- mintaillesztés

Test>
R :: Direction
Test>
[R, L, R, R, L] :: [Direction]

Feladat: Háromértékű válasz

Definiáljuk az Answer típust:


Test>
Test>
Test>

Feladat: logikai “ÉS” válaszokra

Definiáljuk a logikai “ÉS” függvényt az Answer típusra!

(&&&) :: Answer -> Answer -> Answer
infixr 3 &&&

Test>
Maybe :: Answer
Test>
No :: Answer

Feladat: logikai “VAGY” válaszokra

Definiáljuk a logikai “VAGY” függvényt az Answer típusra!

(|||) :: Answer -> Answer -> Answer
infixr 2 |||

Test>
Yes :: Answer
Test>
Maybe :: Answer

Feladat: Égtájak

Definiáljuk a négy égtájat!


Test>
Test>
Test>
Test>

Feladat: Balra fordulás

Definiáljuk a 90 fokos balra fordulást.

turnLeft :: CardinalPoint -> CardinalPoint

Test>
East :: CardinalPoint

Feladat: Jobbra fordulás

Definiáljuk a 90 fokos jobbra fordulást.

turnRight :: CardinalPoint -> CardinalPoint

Test>
West :: CardinalPoint

Feladat: Megfordulás

Definiáljuk a 180 fokos fordulást.

turnBack :: CardinalPoint -> CardinalPoint

Test>
North :: CardinalPoint

Feladat: Bitek [*]

Definiáljuk a két bitet!


Test>
Test>

Feladat: Bináris számok [*]

Definiáljuk a bináris számokat mint bitek listáját (a type kulcsszóval)!


Test>
Test>
Test>
Test>
Test>

(A következő függvényeket könnyebb implementálni, ha az alacsonyabb helyiértékű bitek vannak elöl a listában.)

Feladat: Következő bináris szám [*]

Definiáljuk a plus1 függvényt, amely megmondja milyen szám a következő!

plus1 :: Binary -> Binary

Test>
[Zero, Zero, One] :: Binary

Feladat: Összeadás [*]

add  :: Binary -> Binary -> Binary

Test>
[One, Zero, One] :: Binary

A Bool típus

A Bool típus definíciója a Prelude-ben:

-- data Bool 
--     = False 
--     | True
--         deriving (Eq, Ord, Show, Read, Enum)

A Bool tehát nem beépített típus.

Az algebrai adattípusok nem szerkezet alapján azonosak, tehát ha a fenti módon definiáljuk a Bool típust, akkor arra nem fog működni a Prelude.not függvény, mert az a Prelude.Bool-ra van definiálva.

A Char és Int típusokat is le lehet írni elméletileg algebrai adattípussal.

Hatékonysági okokból Char és Int beépített típusok.

Az Integer típus algebrai adattípussal való leírásához végtelen sok konstruktorra lenne szükség:

A Haskell 98 ezt nem engedi:

Az Ordering típus

A Prelude-ben így definiálták az Ordering típust:

data Ordering
    = LT
    | EQ
    | GT
        deriving (Eq, Ord, Show, Data, Typeable)

Összetett algebrai típusok

Példa:

data Color
    = Named String
    | RGB Int Int Int
    | HSV Float Float Float
        deriving (Show)

(Redundáns ábrázolás, ezért nem bízzuk a fordítóra az egyenlőségvizsgálat definiálását.)

Kérdezzük meg Named, RGB, HSV és RGB 0 0 0 típusát!

Használat

toRGB :: Color -> Color
toRGB (Named "black") = RGB 0   0   0
toRGB (Named "white") = RGB 255 255 255
toRGB (Named "red")   = RGB 255 0   0
-- ...
toRGB color@(RGB r g b) = color
-- toRGB (HSV h s v) = ... -- konverzió

A HSV h s v minta a HSV alakban tárolt színekre illeszkedik. A komponenseket a h, s, v változókhoz kötjük.

Feladat: Sakkbábuk

Definiáljuk a sakkbábukat úgy, hogy a futónál jelezzük, hogy milyen színű mezőn van.


Test>
Test>
Test>

ahol

data BlackOrWhite
    = Black
    | White
      deriving (Data, Typeable)

A sakkbábuk nevei: king, queen, rook, knight, bishop, pawn.