U L i k o o L matemaatika-informaatikateaduskond



Yüklə 0,53 Mb.
Pdf görüntüsü
səhifə14/23
tarix13.11.2017
ölçüsü0,53 Mb.
#9782
1   ...   10   11   12   13   14   15   16   17   ...   23

public boolean equal(Equal other) {

return x == ((MyInt) other).x;

}

}

Siin abstraktse funktsiooni equal definitsioon s˜oltub konkreetsest klassi Equal



alamklassist, kuid funktsioon notequal defineeritakse selle kaudu juba ¨ulem-

klassis. Selle alamklassi funktsiooni equal realisatsioon antakse implitsiitse

parameetrina (nn this-argumendi koosseisus) funktsioonile notequal sel-

le v¨aljakutsumisel. Alamklassi definitsioon ei pea olema ¨ulemklassi definee-

rimisel k¨attesaadav, implitsiitse parameetri v¨a¨artus v˜oetakse d¨unaamilisest

skoobist.

6.4

Pol¨


umorfsed v¨

artused funktsiooni argumendina



6.4.1

Pol¨


umorfsed v¨

artused



Seni vaatlesime pol¨umorfismi funktsioonide jaoks, mis v˜oivad argumendiks

v˜otta erinevat t¨u¨upi v¨a¨artusi ning k¨aituda nende korral kas ¨uhtemoodi v˜oi

erinevalt. Pol¨umorfsed v˜oivad aga lisaks funktsioonidele olla ka mittefunktsio-

naalsed v¨a¨artused, mis samuti v˜oivad olla erinevate t¨u¨upide korral kas samal

v˜oi erineval sisemisel kujul. Neid v¨a¨artusi on vastavalt vajadusele v˜oimalik

kasutada erinevat t¨u¨upi v¨a¨artustena.

Pol¨umorfsete funktsioonide korral saab funktsiooni k¨aitumise ja tulemuse

t¨u¨ubi m¨a¨arata (monomorfse) argumendi t¨u¨ubi p˜ohjal. Pol¨umorfsete v¨a¨artuste

korral saab nende t¨u¨ubi m¨a¨arata selle (monomorfse) funktsiooni deklareeri-

tud argumendi t¨u¨ubi j¨argi, millele see v¨a¨artus argumendiks antakse.

Seega kui pol¨umorfne on ainult funktsioon v˜oi ainult argument, kuid mitte

m˜olemad, siis ei teki probleeme argumendile monomorfse t¨u¨ubi m¨a¨aramise-

ga ja seej¨arel tulemuse t¨u¨ubi m¨a¨aramisega, kuna see monomorfne t¨u¨up on

¨uheselt m¨a¨aratud (eeldusel, et vaadeldav pol¨umorfne t¨u¨up vaadeldava mono-

morfse t¨u¨ubiga ¨uldse koosk˜olas on).

Probleem tekib siis, kui pol¨umorfsed on nii funktsioon kui sellele argu-

mendiks antud v¨a¨artus. Siis ei pruugi tulemuse t¨u¨up enam ¨uheselt m¨a¨ara-

tud olla. Kui funktsioonile Fumontrixi t¨u¨upi forall A. Pair A Int -> A

anda argument t¨u¨upi forall B. Pair Bool B, siis on tulemuse t¨u¨up Bool

veel ¨uheselt m¨a¨aratud. Kui aga funktsioonile t¨u¨upi forall A. A -> List A

anda argument t¨u¨upi forall B. List B, siis v˜oib tulemus olla nii t¨u¨upi

forall B. List (List B) (kui v¨a¨artustatakse A = List B) kui ka

List (forall B. List B) (kui v¨a¨artustatakse A = forall B. List B).

See probleem tekib sellisel juhul, kui funktsiooni t¨u¨ubis on argumendi

koha peal (kontravariantses positsioonis) ainult t¨u¨ubimuutuja, mis on selle

45



funktsiooni t¨u¨ubi tipmisel tasemel kvantoriga seotud. Seda t¨u¨ubimuutujat

on v˜oimalik unifitseerida iga t¨u¨ubiga ja seega juhul, kui argumendiks antud

v¨a¨artuse t¨u¨up sisaldab tipmisel tasemel kvantoreid, siis on v˜oimalik ¨uks k˜oik

mitu nendest kvantoritest avada (kas k˜oik, m˜oned v˜oi mitte ¨uhtegi) enne

unifitseerimist. Avamata kvantorid l¨ahevad tulemuse t¨u¨ubi ette.

Kui funktsiooni t¨u¨ubis argumendi koha peal on midagi muud kui ainult

t¨u¨ubimuutuja, siis seda probleemi ei teki. Kui seal on tipmisel tasemel konst-

ruktor (v˜oi olemasolukvantor), siis tuleb igal juhul argumendiks antava v¨a¨ar-

tuse k˜oik tipmised ¨uldisuskvantorid avada, et unifitseerimine v˜oimalik oleks.

Kui seal on tipmisel tasemel ¨uldisuskvantor, siis tuleb argumendis antavas

v¨a¨artuses avada nii palju kvantoreid, et avamata j¨a¨anud tipmiste kvantorite

arv saaks v˜ordseks funktsiooni t¨u¨ubis argumendi koha peal olevate tipmiste

kvantorite arvuga.

6.4.2


Impredikatiivne pol¨

umorfism


Eelmises alajaotises vaadeldud probleemi v¨altimiseks on Haskell 98-s keela-

tud impredikatiivne pol¨umorfism. Impredikatiivne pol¨umorfism v˜oimaldab

kvantifitseeritud t¨u¨ubimuutuja v¨a¨artustada pol¨umorfse t¨u¨ubiga. Seega Has-

kell 98-s v¨a¨artustatakse eelnevas n¨aites A = List B ja kvantorid j¨a¨avad alati

tipmisele tasemele.

Ka GHC-s ja Fumontrixis valitakse selles n¨aites sama v¨a¨artustus, kuid

siin on v˜oimalik teatud juhtudel ka impredikatiivsust kasutada (GHC impre-

dikatiivsuse kohta vt [2], jaotis 8.7.5). Defineerime n¨aiteks GHC-s

f1 :: forall a. a -> [a]

f1 = undefined

v2 :: forall b. [b]

v2 = undefined

Siis f1 v2 on t¨u¨upi forall b. [[b]], aga

(f1 :: (forall b. [b]) -> [forall b. [b]]) v2

annab tulemuse t¨u¨ubiks [forall b. [b]], kuna siin v¨a¨artustatakse f1 t¨u¨u-

bis muutuja a ilmutatult t¨u¨ubiga forall b. [b]. Pol¨umorfse v¨a¨artuse t¨u¨u-

bis t¨u¨ubimuutuja ilmutatud v¨a¨artustamine on GHC-s kohmakas, kuna sel-

leks tuleb kogu v¨a¨artuse t¨u¨up ¨umber kirjutada ja asendada seal muutuja k˜oik

esinemised selle soovitava t¨u¨ubiga. Selleks, et seda soovitavat t¨u¨upi ei peaks

mitu korda v¨alja kirjutama, v˜oiks defineerida t¨u¨ubis¨unon¨u¨umi:

type T1 = forall b. [b]

ja siis kasutada

46



(f1 :: T1 -> [T1]) f2

Samas saab GHC-s t¨u¨ubis¨unon¨u¨umi defineerida ainult peataseme skoobis

ning, kui seda t¨u¨ubimuutuja v¨a¨artustamist on vaja teha kuskil s¨ugavas alam-

skoobis, siis j¨a¨ab kood hakituks. Samuti on vaja selle pol¨umorfse v¨a¨artuse

t¨u¨ubi struktuur ¨umber kirjutada ning see struktuur v˜oib m˜onikord olla v¨aga

keeruline.

Fumontrixis v˜oime defineerida

f1 = bottom $: (forall A. A -> List A);

v2 = bottom $: (forall B. List B);

Siis f1 v2 on t¨u¨upi forall B. List (List B), aga

f1 $: (forall B. List B) v2

on t¨u¨upi List (forall B. List B). Operaator $: avab tipmise taseme

¨uldisuskvantori ja v¨a¨artustab sellega seotud muutuja antud t¨u¨ubiga, seega

erinevalt GHC-st ei pea Fumontrixis kogu v¨a¨artuse t¨u¨upi ¨umber kirjutama,

vaja on kirjutatada vaid see t¨u¨up, millega muutuja v¨a¨artustatakse. Fumon-

trixis v˜oime kasutada ka typeof-operaatorit ja kirjutada viimase n¨aitega

samav¨a¨arse

f1 $: (typeof v2) v2

Kui me ei soovi argumenti kaks korda v¨alja kirjutada (see v˜oib olla n¨aiteks

mingi keeruline avaldis), siis v˜oime defineerida eraldi funktsiooni rakendamise

operaatori t¨u¨ubitaseme funktsioonina:

type applyImpred = \ f : @ . \ x : @ .

value (type f) $: (typeof type x) (type x);

ja siis kasutada

type applyImpred (value f1) (value v2)

Operaator applyImpred on kasutatav sel juhul, kui funktsiooni t¨u¨ubis argu-

mendi kohal on t¨u¨ubimuutuja, mis on seotud selle funktsiooni t¨u¨ubis k˜oige

tipmisel tasemel asuva ¨uldisuskvantoriga.

Impredikatiivne pol¨umorfism v˜oib esineda ka sel juhul, kui t¨u¨ubimuutuja

ei esine funktsiooni t¨u¨ubis otse argumendi kohal, vaid on seal n¨aiteks mingi

konstruktori parameetriks. N¨aiteks GHC-s

f3 :: forall a. [a] -> [a]

f3 = undefined

v4 :: [forall b. [b]]

v4 = undefined

47



Yüklə 0,53 Mb.

Dostları ilə paylaş:
1   ...   10   11   12   13   14   15   16   17   ...   23




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə