U L i k o o L matemaatika-informaatikateaduskond



Yüklə 0,53 Mb.

səhifə3/23
tarix13.11.2017
ölçüsü0,53 Mb.
1   2   3   4   5   6   7   8   9   ...   23

Nii lubatakse k¨ull Haskellis kirjutada, aga see ei ole vajaliku semantikaga,

kuna Haskellis on let-deklaratsioonid alati (potentsiaalselt) rekursiivsed ja

teises let-is v˜ordusm¨argist paremal olevad muutuja r kasutused viitavad

rekursiivselt sellele samale teise let-i muutujale r, mitte esimese let-i omale.

Seega ei j¨a¨a muud v˜oimalust kui nimetada ¨uks muutujatest ¨umber, n¨ai-

teks esimese r asemel r0 v˜oi teise r asemel r’. Programmeerija jaoks on

muutujanimede v¨aljam˜otlemine ja meeldej¨atmine suur vaev ning selliste sar-

naste t¨ahenduste ja nimedega muutujate nimed v˜oivad kergesti segamini min-

na. Seega programmeerija v˜oib kogemata kasutada vale muutujat, kuigi ta

teadis, et vaja on kasutada ainult viimasena defineeritud muutujat. Kui keel

lubaks defineerida mitu sama nimega muutujat, siis seda probleemi ei esineks,

kuna k¨attesaadav on ainult viimane definitsioon.

Seet˜ottu Fumontrixis on let-deklaratsioonid vaikimisi mitterekursiivsed

ning ¨uhes let-avaldises saab defineerida mitu samanimelist muutujat. K¨at-

tesaadav on kasutamise kohale eelnevatest samanimeliste muutujate definit-

sioonidest viimane. Fumontrixis v˜oib eelneva n¨aite kirjutada nii:

let

r = x % m;



r = if (r*2 < m)

r

(r - m);



in

f r


Rekursiivse v¨a¨artuse defineerimiseks saab kasutada rec-deklaratsiooni:

let


rec ones : List Int = 1 :: ones;

in

f ones



Seega Fumontrixis saab koodi lugeda ¨ulevalt alla, kuna viidata saab vaid

eelnevatele definitsioonidele. Vaid rec-deklaratsiooni korral on v˜oimalik vii-

data pooleliolevale definitsioonile, kuid sel juhul tuleb lisaks muutuja nimele

definitsiooni alguses deklareerida ka muutuja t¨u¨up. Seega kasutamise hetkeks

on muutuja t¨u¨up juba lugejale teada.

2.2


ubiinferents



Haskellis kasutatakse Hindley-Milneri t¨u¨ubituletusalgoritmi ([1], jaotis 4.5).

Et eristada sellist unifitseerimist ja v˜orrandite lahendamist kasutavat t¨u¨ubi-

tuletust tavalisest (lihtsamast) t¨u¨ubituletusest, nimetame selles t¨o¨os esimest

9



t¨u¨ubiinferentsiks. T¨u¨ubiinferentsiga sarnast meetodit liikide m¨a¨aramiseks ni-

metame liigiinferentsiks.

Hindley-Milneri t¨u¨ubiinferentsi korral m¨a¨arab translaator paljudele muu-

tujatele ise t¨u¨ubi, seega programmeerija ei pea alati t¨u¨ubiannotatsioone li-

sama. Samas muudab see koodi lugemise raskemaks, kuna t¨u¨ubiinferentsi

algoritmi peast rakendamine v˜oib keerulisematel juhtudel liiga raskeks osu-

tuda. Samuti s˜oltub muutuja t¨u¨up tema kasutustest, mis v˜oivad esineda koo-

dis selle definitsioonist palju hiljem. See l¨aheb vastuollu ¨ulalt alla loetavuse

p˜ohim˜ottega.

Haskell lubab lisada muutujadefinitsioonidele t¨u¨ubisignatuure, kuid nen-

de kasutamine ei ole kohustuslik. Funktsiooni t¨u¨ubisignatuur peab sisalda-

ma ka tagastusv¨a¨artuse t¨u¨upi, mis mitterekursiivsete funktsioonide korral ei

oleks tegelikult vajalik, kuna tagastusv¨a¨artuse t¨u¨ubi saab lihtsalt argumen-

tide t¨u¨upide j¨argi leida.

Fumontrixis (nagu ka GHC-s) on v˜oimalik kasutada k˜orgemat j¨arku uni-

versaalselt kvantifitseeritud t¨u¨upe. ¨

Uldjuhul on aga k˜orgemat j¨arku t¨u¨upide

korral t¨u¨ubiinferents mittelahenduv ([2], jaotis 8.7.4.2). Ka GHC-s on vaja

teist ja k˜orgemat j¨arku t¨u¨upide kasutamisel annotatsioonid lisada.

Seet˜ottu Fumontrixis Haskelli stiilis t¨u¨ubiinferentsi ei kasutata. Selle ase-

mel tuleb λ-seotud muutujate sissetoomisel t¨u¨ubid juurde kirjutada. N¨aiteks:

succ = \ x : Int . x + 1

let- ja case-seotud muutujate korral t¨u¨upi juurde pole vaja lisada (v.a rec-

deklaratsioonide korral), kuna seal on muutuja v¨a¨artustamiseks kasutatav

avaldis kohe juures ja selle t¨u¨up on teada.

Samuti ei ole Fumontrixis liigiinferentsi. Seega tuleb kvantoriga t¨u¨ubi-

muutuja sissetoomisel lisada liigiannotatsioon. Liigiannotatsiooni v˜oib ¨ara

j¨atta, kui liigiks on *.

2.3

Skoopide v˜



ordv¨

arsus



Haskellis on peataseme skoop v¨aga erinev tavalisest alamskoobist. T¨u¨ubiklas-

se, esindajaid, algebralisi andmet¨u¨upe, t¨u¨ubis¨unon¨u¨ume on v˜oimalik definee-

rida ainult peatasemel. Seega need definitsioonid on k˜oik globaalselt k¨atte-

saadavad ja kogemata on v˜oimalik mingis kohas kasutada definitsiooni, mida

tegelikult ei tohiks seal kasutada. Mingil m¨a¨aral on moodulite abil v˜oimalik

definitsioone peita, kuid v¨aga v¨aikesteks juppideks ei ole m˜otet koodi t¨ukelda-

da, seega see on kasutatav p˜ohiliselt suuremate alamskoopide jaoks. Samuti ei

ole ¨uhes Haskelli moodulis v˜oimalik defineerida t¨u¨ubiklassi, andmet¨u¨upi jne,

millega samanimeline olem (nimetame olemiks k˜oiki asju, millele on v˜oimalik

10



koodis mingi identifikaatoriga viidata) on juba m˜ones kasutatavas moodulis

defineeritud (ja eksporditud).

Fumontrixis on t¨u¨ubiklasse, t¨u¨ubitaseme funktsioone, algebralisi andme-

t¨u¨upe jne v˜oimalik defineerida k˜oigis skoopides — nii peatasemel kui let-

avaldistes. Samuti on v˜oimalik defineerida uut olemit, mille nimi langeb kok-

ku m˜one olemasolevaga. Sellisel juhul alamskoobis enam vanale olemile selle

nimega viidata ei saa, kuid see v˜oib j¨a¨ada kaudselt k¨attesaadavaks.

2.4


orvalefektid, erindid ja laiendatud t¨

ubid


Paljudes keeltes v˜oivad avaldiste v¨a¨artused sisaldada lisaks tavalisele v¨a¨ar-

tusele k˜orvalefekte. N¨aiteks Java funktsioon, mille tagastusv¨a¨artuse t¨u¨ubiks

on boolean, v˜oib enne t˜oev¨a¨artuse tagastamist teha mingeid k˜orvalefekte

(muuta muutujate v¨a¨artusi, teha sisendit-v¨aljundit jne) v˜oi tagastada t˜oe-

v¨a¨artuse asemel midagi muud (nt erindi, m˜onede teiste t¨u¨upide korral ka

nullviida). Seega Java t¨u¨up boolean on v¨aga erinev matemaatilisest (kahe-

elemendilisest) t˜oev¨a¨artust¨u¨ubist. Samas v˜oib ka Java funktsioon tagastada

t˜oev¨a¨artuse ilma erindita ja k˜orvalefekte tegemata, seega Java t¨u¨up boolean

sisaldab alamt¨u¨ubina matemaatilist t˜oev¨a¨artust¨u¨upi. V˜oime ¨oelda, et Javas

on kasutusel laiendatud t˜oev¨a¨artust¨u¨up.

Kui t¨u¨ubis¨usteem toetab ainult laiendatud boolean-i, siis me ei saa lasta

t¨u¨ubis¨usteemil staatiliselt kontrollida, et funktsiooni tagastusv¨a¨artus kuulub

puhta boolean-i t¨u¨upi. Et garanteerida, et tagastusv¨a¨artus ei sisalda erin-

deid, on vaja k¨asitsi kontroll koodi sisse kirjutada. Kuid sellisel juhul on v˜oi-

malik t¨u¨ubiveast teada saada alles p¨arast koodi k¨aivitamist, seega tegemist

on d¨unaamilise t¨u¨ubikontrolliga.

Kui me soovime, et keel oleks staatilise t¨u¨ubikontrolliga (nagu Haskell),

siis peaks ka puhast boolean-i ja laiendatud boolean-i saama staatiliselt

eristada, vastasel korral on t¨u¨ubikontroll ainult pooleldi staatiline ja pooleldi

d¨unaamiline. Kui on olemas puhas boolean, siis sellest saab vajaduse korral

laiendatud boolean-i defineerida (n¨aiteks monaadide abil), vastupidine ei ole

aga v˜oimalik nii, et staatiline t¨u¨ubikontroll s¨ailiks.

Vaatleme, milleks on kasulik, kui on olemas puhas boolean (mitte ai-

nult laiendatud boolean). N¨aiteks olgu tegemist kr¨uptoloogilise teegiga. Seal

on mingi funktsioon, mis kasutab salajasi andmeid ja tagastab kasutajale

ainult ¨uhe biti informatsiooni. Kasutaja v˜oib olla pahatahtlik ja ¨uritab sala-

jaste andmete kohta infot saada. Kui funktsiooni tagastust¨u¨ubiks on puhas

boolean, siis ta ei saa ¨uhe p¨aringuga k¨atte rohkem kui ¨uhe biti salajast in-

formatsiooni. Kui funktsiooni tagastust¨u¨ubiks on laiendatud boolean, siis

ta v˜oib turvaauke ¨ara kasutades panna funktsiooni tagastama erindit, mis

sisaldab palju rohkem kui ¨uhe biti salajast informatsiooni.

11





Dostları ilə paylaş:
1   2   3   4   5   6   7   8   9   ...   23


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

    Ana səhifə