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"