Siis f3 v4 on t¨u¨upi [forall b. [b]]. Siin ei ole vaja ilmutatult t¨u¨ubimuu-
tujat v¨a¨artustada, kuna siin on unifitseerimine v˜oimalik ainult ¨uhel viisil.
Analoogiliselt Fumontrixis
f3 = bottom $: (forall A. List A -> List A);
v4 = bottom $: (List (forall B. List B));
Siin f3 v4 on t¨u¨upi List (forall B. List B).
Praegu vaatlesime parameetrilist pol¨umorfismi. Olukord on analoogiline
juhul, kui kvantifitseeritud muutujatel on t¨u¨ubiklassikitsendused. Keeruli-
sema pol¨umorfismi korral (nagu saab Fumontrixi t¨u¨ubitasemel realiseerida)
tuleb juhul, kus pol¨umorfsed on nii funktsioon kui argument, kasutatav ar-
gumendi t¨u¨up (v˜oi t¨u¨ubid, kui soovime rohkem pol¨umorfismi s¨ailitada) ilmu-
tatult m¨a¨arata.
6.4.3
Pol¨
umorfsed v¨
a¨
artused Fumontrixi t¨
u¨
ubitasemel
Pol¨umorfseid mittefunktsionaalseid v¨a¨artusi v˜oib Fumontrixi t¨u¨ubitasemel
kujutada kui liiki * -> @ funktsioone, mis seavad t¨u¨ubile vastavusse seda
t¨u¨upi v¨a¨artuse. Siin saame kasutada k˜oiki Fumontrixi t¨u¨ubitaseme program-
meerimise v˜oimalusi, sh lihtrekursiooni, seega on v˜oimalik kujutada palju
keerulisemaid pol¨umorfseid v¨a¨artusi kui andmetasemel.
Samas nende t¨u¨ubitaseme v¨a¨artuste kasutamine on ebamugavam kui and-
metaseme pol¨umorfsete v¨a¨artuste kasutamine. Kui me soovime neid anda
argumendiks (potentsiaalselt pol¨umorfsele) t¨u¨ubitaseme funktsioonile liiki
@ -> @, siis peame selle liiki * -> @ v¨a¨artuse teisendama monomorfseks liiki
@ v¨a¨artuseks, m¨a¨arates liiki * t¨u¨ubiparameetri. Saadud monomorfse v¨a¨artu-
se saame anda argumendiks t¨u¨ubitaseme funktsioonile. Rakendame n¨aiteks
t¨u¨ubitaseme pol¨umorfset funktsiooni tf t¨u¨ubitaseme pol¨umorfsele v¨a¨artusele
pv, m¨a¨arates viimase t¨u¨ubiks Int:
type tf (pv Int)
Kuna siin pol¨umorfne argument muudetakse enne (pol¨umorfse) funkt-
siooni rakendamist ilmutatult monomorfseks, siis ei teki siin neid eelmises
jaotises vaadelnud probleeme, mis tekivad, kui nii funktsioon kui argument
on pol¨umorfsed. Kui see t¨u¨ubitaseme funktsioon on monomorfne, siis tundub
see argumendi monomorfseks muutmine ¨ulearune, aga monomorfne t¨u¨ubita-
seme funktsioon on alati v˜oimalik andmetaseme funktsioonina realiseerida.
Olgu n¨aiteks t¨u¨ubitaseme funktsiooni tf oodatava argumendi t¨u¨up Int. Siis
vastav andmetaseme funktsioon oleks
\ x : Int . type tf (value x)
48
Kui soovime t¨u¨ubitaseme pol¨umorfse funktsiooni rakendamisel t¨u¨ubitase-
me pol¨umorfsele v¨a¨artusele saada tulemuseks pol¨umorfset v¨a¨artust, siis v˜oi-
me rakendamisel m¨a¨arata pol¨umorfsele v¨a¨artusele ka rohkem kui ¨uhe mo-
nomorfse t¨u¨ubi ning j¨atta konkreetse monomorfse t¨u¨ubi s˜oltuma pol¨umorfse
tulemuse t¨u¨ubiparameetrist. N¨aiteks
\ t .
case t of
Bool
-> tf (pv Int);
List a -> tf (pv (Maybe a));
end;
Siin peaks siis tf t¨aisarvulise argumendi korral tulemuseks andma t˜oev¨a¨ar-
tuse ning Maybe-t¨u¨upi argumendi korral listi.
T¨u¨ubitaseme pol¨umorfsele v¨a¨artusele v˜oime soovida rakendada ka andme-
taseme funktsiooni. Kui see funktsioon on monomorfne, siis t˜oen¨aoliselt see
ongi andmetasemel realiseeritud. Sellisel juhul saame funktsiooni argumendi
t¨u¨ubi leidmiseks kasutada jaotises 5.1.2 defineeritud t¨u¨ubitaseme funktsiooni
argtype ja ei pea seda t¨u¨upi ilmutatult v¨alja kirjutama. Andmetaseme mo-
nomorfse funktsiooni f rakendamine t¨u¨ubitaseme pol¨umorfsele v¨a¨artusele pv
oleks siis
f (type pv (argtype (value f)))
Selle asemel v˜oime defineerida ka t¨u¨ubitaseme funktsiooni
type applyMtp = \ f : @ . \ pv : * -> @ .
value f (type pv (argtype (value f)));
Seda saab siis kasutada funktsiooni rakendamise operaatorina juhul, kui funkt-
sioon on andmetaseme monomorfne funktsioon ja argument on t¨u¨ubitaseme
pol¨umorfne v¨a¨artus. Eelmine n¨aide oleks siis
type (value f) ‘applyMtp‘ pv
Kui me soovime t¨u¨ubitaseme pol¨umorfsele v¨a¨artusele rakendada andme-
taseme pol¨umorfset funktsiooni, siis selleks on kaks v˜oimalust. Esimene v˜oi-
malus on muuta see funktsioon monomorfseks, m¨a¨arates t¨u¨ubiparameetri
operaatoriga $: ja kasutades applyMtp operaatorit:
type applyMtp (value f $: t1) pv
Teine v˜oimalus on muuta t¨u¨ubitaseme pol¨umorfne v¨a¨artus andmetaseme mo-
nomorfseks v¨a¨artuseks, m¨a¨arates vastava monomorfse t¨u¨ubi, ja seej¨arel anda
funktsioonile argumendiks:
49
f (type pv t2)
See teine v˜oimalus on l¨uhem, v.a juhul, kui t2 on oluliselt keerulisem t¨u¨up
kui t1. Need t¨u¨ubid ei pruugi v˜ordsed olla, kuna t2 argumendi monomorfne
t¨u¨up, kuid t1 on t¨u¨ubiparameeter, millest argumendi t¨u¨up s˜oltub (neid t¨u¨ubi-
parameetreid v˜oib ka mitu olla, siis tuleb kasutada n¨aiteks f $: t1a $: t1b
jne).
6.5
Monaadilised v¨
a¨
artused ja pol¨
umorfism
6.5.1
Monaadilised v¨
a¨
artused ja funktsiooni rakendamine
Nagu Haskell, on ka Fumontrix puhas funktsionaalne keel ning k˜orvalefekti-
de ja erindite jaoks kasutatakse monaade. Monaadid v˜oimaldavad kasutada
imperatiivset programmeerimisstiili puhtalt funktsionaalses keeles.
GHC-s on olemas ST-monaad, milles saab programmeerida imperatiivses
stiilis, kasutades n¨aiteks viitasid ja massiive. Funktsiooni runST abil saab
ST-monaadist ohutult v¨aljuda.
Samas on GHC-s ¨usna ebamugav kasutada korraga monaadilisi ja tavalisi
v¨a¨artusi. N¨aiteks SML-is saab k˜orvalefekte sisaldavaid t¨aisarvulisi v¨a¨artusi
ja puhtaid t¨aisarvulisi v¨a¨artusi anda argumendiks ¨uhele ja samale (t¨aisarvu
ootavale) funktsioonile, kuna need v¨a¨artused on sama t¨u¨upi. GHC-s on need
v¨a¨artused erinevat t¨u¨upi (Integer ja M Integer, kus M on mingi monaad) ja
nende argumendiks andmiseks t¨u¨upi Integer v¨a¨artust ootavale funktsiooni-
le tuleb kasutada erinevaid funktsiooni rakendamise operaatoreid, vastavalt
tavalist funktsiooni rakendamise operaatorit ning funktsiooni liftM.
Samuti tuleb kasutada erinevaid operaatoreid, kui funktsiooni tulemus
v˜oi kogu funktsioon ise on monaadiline v¨a¨artus. Kui kasutada korraga mak-
simaalselt ¨uhte monaadi, siis on kokku 16 erinevat kombinatsiooni funktsiooni
ja argumendi t¨u¨upide jaoks:
f
x
f x
GHC standardfunktsioonidega
-----------------------------------------------------------
a -> b
a
b
f x
a -> M b
a
M b
f x
M (a -> b)
a
M b
f ‘ap‘ return x
M (a -> M b)
a
M b
join (f ‘ap‘ return x)
a -> b
M a
M b
f ‘liftM‘ x
a -> M b
M a
M b
f =<< x
M (a -> b)
M a
M b
f ‘ap‘ x
M (a -> M b)
M a
M b
join (f ‘ap‘ x)
M a -> b
a
b
f (return x)
50
Dostları ilə paylaş: |