Liidesed
Liidesed (Haskellis tüübiklassid) on viis kuidas kasutada ad-hoc polümorfismi s.t. erinevatele tüüpidele erinev implementatsioon. (See vastandub parameetrilisele polümorfismile, kus on kõikidele tüüpidele sama implementatsioon.)
Saame teha liidese
interface Equal a where (==) : a -> a -> Bool Equal Int where a == b = ?eq_Int -- Int'ide võrdsus Equal Bool where a == b = ?eq_Bool -- Bool'ide võrdsus
Ehk siis saame kirjutada 5 == 6
, mis kasutab täisarvude võrdlust, ja True == True
, mis kasutab Bool
-ide võrdlust.
Idrise standardteegis on defineeritud liides (tüübiklass) Eq
:
interface Eq a where (==), (/=) : a -> a -> Bool -- Minimaalne definitioon peab sisaldama: -- (==) või (/=) x /= y = not (x == y) -- vaikedefinitsioon x == y = not (x /= y) -- vaikedefinitsioon
Võrdlusoperaatori tüüp on:
(==) : Eq a => a -> a -> Bool
s.t me saame operaatorit kasutada, kui tema argumenditüübil on defineeritud Eq
instants!
Kõikidel polümorfsetel funktsioonidel, mis kasutavad võrdust, peab tüübi kontekstis olema Eq
:
lookup : Eq a => a -> List (a, b) -> Maybe b
Oma andmestruktuuri defineerimisel oleks mõistlik defineerida selle jaoks ka võrdus:
data ValgusFoor = Punane | Kollane | Roheline Eq ValgusFoor where Punane == Punane = True Kollane == Kollane = True Roheline == Roheline = True _ == _ = False test : Bool test = Kollane == Roheline -- False
Liideste hierarhiad
Liidestel võivad olla kitsendused nii, et moodustuvad liideste hierarhiad
interface Equal a => Order a where comp : a -> a -> Ordering -- LT, EQ, GT (<=) : a -> a -> Bool max : a -> a -> a min : a -> a -> a x <= y = comp x y /= GT max x y = if x<=y then y else x min x y = if x<=y then x else y
Range tüübiklass
Enumeratsioone kirjeldab järgnev tüübiklass:
interface Range a where rangeFromTo : a -> a -> List a -- [x..y] rangeFromThenTo : a -> a -> a -> List a -- [x,y..z] rangeFrom : a -> Stream a -- [x..] rangeFromThen : a -> a -> Stream a -- [x,y..]
Ehk, näiteks
[1..5] == [1, 2, 3, 4, 5]} [5..1] == [5, 4, 3, 2, 1] -- Haskellis on [] [0,2..10] == [0, 2, 4, 6, 8, 10] [0,2..11] == [0, 2, 4, 6, 8, 10] [10,7..(-3)] == [10, 7, 4, 1, -2]}
lõpmatud, laisad „listid“ ehk Stream
-id
[1..] == [1, 2, 3, 4, 5, 6, 7, ... lõpmatu voog! [1,3..] == [1, 3, 5, 7, 9, 11, ... lõpmatu voog!
Voogudest räägime lähemalt natuke hiljem (koos laiskuse teemaga).
Liideste implementatsioon ja nimelised instantsid
Liidesed on kirjete eriliik.
interface MinuShow a where constructor MkShow minu_show : a -> String
Nagu kirje väärtustele saab ka instantsidele anda nimesid. Näiteks:
[showVF] MinuShow ValgusFoor where minu_show Punane = "PP" minu_show Kollane = "KK" minu_show Roheline = "RR"
Õige instantsi peab siis valima käsitsi @{...}
süntaksiga.
Main> minu_show @{showVF} Punane "PP"
Aga instantsi loomiseks saab kasutada ka konstruktorit.
showvf : MinuShow ValgusFoor showvf = MkShow (\ a => case a of Punane => "p" Kollane => "k" Roheline => "r" )
Main> minu_show @{showvf} Punane "p"
Mis teeb liidesed ja instantsid erinevaks võrreldes kirjetega on instantside automaatne leidmine.
MinuShow ValgusFoor where minu_show Punane = "P" minu_show Kollane = "K" minu_show Roheline = "R"
Main> minu_show Punane "P" Main> minu_show @{%search} Punane "P"