(_ -> Int) ->
value const True $: t;
end;
end
) (typeof type v)
) (type v);
Siin kasutatakse anon¨u¨umset t¨u¨ubitaseme funktsiooni, mis seab t¨u¨ubile (ku-
na lihtrekursiooni saab teha ainult ¨ule t¨u¨upide, mitte ¨ule v¨a¨artuste) vastavus-
se monomorfse funktsiooni. Sellele t¨u¨ubitaseme funktsioonile antakse seej¨arel
argumendiks esialgse argumentv¨a¨artuse v t¨u¨up ning saadud monomorfsele
funktsioonile antakse andmetasemel argumendiks v¨a¨artus v.
5.3.5
Vaikevariandid hargnemisel
M˜onikord oleks kasulik t¨u¨ubi j¨argi hargnemisel kasutada vaikevariante, et ei
peaks k˜oiki variante ¨ukshaaval v¨alja kirjutama. Kirjutame n¨aiteks
class C6 a where
f6 :: a -> Integer
instance C6 Bool where
f6 = bool2int
instance C6 a where
f6 = const 3
Siin peaks f6 t˜oev¨a¨artuste korral k¨aituma ¨uhtmoodi, aga ¨ulej¨a¨anud t¨u¨upide
v¨a¨artuste korral teistmoodi. Neid deklaratsioone GHC vaikimisi ei aktseptee-
ri, kuna t¨u¨ubi a kohta k¨aiv deklaratsioon oleks rakendatav ka t¨u¨ubile Bool.
GHC-s on v˜oimalik sisse l¨ulitada lipp -fallow-incoherent-instances, selli-
sel juhul valib GHC k˜oige t¨apsema (k˜oige v¨aiksema muutujate arvuga) esin-
dajadeklaratsiooni, mis vaadeldava t¨u¨ubiga sobib. Seega t¨u¨ubi Bool jaoks
valitakse esimene esindajadeklaratsioon, ¨ulej¨a¨anud t¨u¨upide jaoks teine.
Haskellis on v˜oimalik kasutada ka vaikedefinitsioone. N¨aiteks
class C6 a where
f6 :: a -> Integer
f6 = const 3
instance C6 Bool where
f6 = bool2int
instance C6 Char
instance C6 [a]
36
See v˜oimaldab f6 definitsiooni m˜onedest esindajadeklaratsioonidest ¨ara j¨at-
ta, kuid esindajadeklaratsioone siiski ¨ara j¨atta ei saa ning seega on tegemist
vaid s¨untaktilise suhkruga ja seda konstruktsiooni me siin l¨ahemalt ei vaatle.
Proovime vaikevariante kasutada ka tulemuse t¨u¨ubi defineerimisel:
class C7 a b | a -> b where
f7 :: a -> b
instance C7 Bool Int where
f7 = bool2int
instance C7 a Bool where
f7 = const True
Seda aga GHC ei luba, isegi kui v˜oti -fallow-incoherent-instances on
sisse l¨ulitatud. Seega siin tuleb k˜oigi vajalike t¨u¨upide jaoks ¨ukshaaval esin-
dajadeklaratsioonid kirjutada, isegi kui k˜oigi jaoks peale ¨uhe on need sama
sisuga. Kui vajalikku t¨u¨upi ei ole veel defineeritud (see defineeritakse teises
moodulis), siis ei saagi kohe seda esindajaks defineerida.
Samuti ei pruugi alati k˜oige t¨apsemat esindajadeklaratsiooni olla. N¨aiteks
class C8 a where
f8 :: a -> Integer
instance C8 (Integer,b,c,d) where
f8 (x,_,_,_) = x
instance C8 (a,Integer,c,d) where
f8 (_,y,_,_) = 10*y
instance C8 (a,b,Integer,d) where
f8 (_,_,z,_) = 100*z
instance C8 (a,b,c,Integer) where
f8 (_,_,_,w) = 1000*w
instance C8 (a,b,c,d) where
f8 (_,_,_,_) = 0
Siin leidub k˜oige t¨apsem deklaratsioon ainult siis, kui nelikus maksimaal-
selt ¨uks t¨u¨up on Integer. Kui neid on mitu, siis sobib mitu deklaratsiooni,
millest ¨ukski pole k˜oige t¨apsem. Antud juhul lubab GHC kasutada funkt-
siooni f8 ainult selliste v¨a¨artuse jaoks, mille t¨u¨ubi nelikus on maksimaalselt
¨uks Integer. Muude variantide kasutamisel tuleb t¨u¨ubiviga. Selleks, et need
muud variandid oleks kasutatavad, tuleb lisada t¨apsemaid esindajadeklarat-
sioone. Antud juhul oleks vaja kokku 2
4
= 16 esindajadeklaratsiooni, et k˜oik
nelikut¨u¨ubid oleks kasutatavad. See muutuks v¨aga kohmakaks, kuna paljud
nendest variantidest oleks sama sisuga.
Vaja oleks, et mitme sobiva esindajadeklaratsiooni korral valitaks nendest
esimene. Siis piisaks nendest viiest esindajadeklaratsioonist. GHC-s seda ei
37
v˜oimaldata. Siin on esindajadeklaratsioonid nagu loogilise programmeerimise
implikatsioonid. Nende implikatsioonide j¨arjekorda ei loeta oluliseks. Loogili-
ses programmeerimises saaks implikatsioonide eeldustesse kirjutada eelmiste
implikatsioonide paremate poolte eitused, aga GHC-s sellist eituse konstrukt-
siooni ei ole ning seda ei saa ka ise defineerida nagu C7 n¨aitest n¨aha (kui see
n¨aide t¨o¨otaks, siis saaks predikaadiga C7 a Bool n˜ouda, et a ei oleks t¨u¨upi
Bool).
Fumontrixis on t¨u¨ubitaseme case-konstruktsioonis v˜oimalik kasutada vai-
kevariante (n¨aidise _ v˜oi t¨u¨ubimuutujate abil) ning variante vaadeldakse nen-
de esinemise j¨arjekorras, esimese sobiva leidmisel enam edasi ei vaadata. Vaa-
deldud C7 n¨aite saab Fumontrixis kirjutada n¨aiteks nii:
type tf7 = \ v : @ .
case typeof type v of
Bool -> value bool2int (type v);
_
-> value True;
end;
C8 n¨aite saab kirjutada nii:
type tf8 = \ v : @ .
value let
Tuple4 x y z w = type v
in type
case typeof type v of
Tuple4 Int b c d -> value x;
Tuple4 a Int c d -> value 10*y;
Tuple4 a b Int d -> value 100*z;
Tuple4 a b c Int -> value 1000*w;
Tuple4 a b c d
-> value 0;
end;
See t¨o¨otab k˜oigi nelikut¨u¨upide korral.
5.3.6
GHC t¨
u¨
ubitaseme funktsioonide puudusi
GHC-s on t¨u¨ubiklasside abil v˜oimalik defineerida pol¨umorfseid andmetase-
me funktsioone. Funktsionaalsete s˜oltuvuste abil on v˜oimalik defineerida ka
funktsioone, mis seavad t¨u¨ubile vastavusse t¨u¨ubi, kuid erinevalt Fumontrixist
ei ole vaikevariantide kasutamine sel juhul v˜oimalik, k˜oik variandid peavad
olema l˜oikumatud.
38