A Miranda programozási nyelv

Polimorfikus erős típusosság

Polimorfikus erős típusosság

A Miranda erősen típusos nyelv, ugyanis minden kifejezésnek és minden részkifejezésnek van típusa. Explicit típusdeklaráció nem szükséges, mivel ha a típus nincs specifikálva, akkor ezt a fordító kikövetkezteti a függvénydefiníció vizsgálata révén. Bármiféle következetlenség (inkonzisztencia), vagy valami konfliktus a specifikált típusok közt fordítási időben megjelenő hibaüzenetet eredményez. Így a típusok explicit specifikálása nagyon is ajánlott, mivel az sok információt ad a definiált függvényről. A felhasználó által definiált típusoknak célszerű beszédes nevet adni, ezzel is növelve a script olvashatóságát.
Két előnye is van annak, hogy típusrendszer adható a nyelvhez. Először is helyes program írására sarkallja a programozót azáltal, hogy csak korrekten típusozott programot fogad el a fordító. Ha például a függvényhívás típusa nem egyezik a függvény definíciójában szereplő megfelelő típussal, akkor fordítási időben hiba generálódik. A másik előnye a típusos nyelvnek, hogy a típusinformációt fel lehet használni arra, hogy hatékony kódot generáljunk.
A típusos nyelvnek van azért néhány hátránya is. Szükséges, hogy befejeződjön a típusok összeillesztése fordítási időben. Bizonyítható, hogy van olyan eset, amikor nem lehet meghatározni minden kifejezés igazi típusát. Szerencsére egy olyan erőteljes típusrendszer, mint a Mirandában használt Milner-Mycroft séma, képes kikövetkeztetni és leellenőrizni a legtöbb kifejezés típusát, de néhány kifejezésnek még ebben a rendszerben sem adható meg a típusa.

Három primitív (alap) típus van, a num, bool, char. A num típus tartalmazza az integer (egész) és a floating point (lebegőpontos) számokat is, a különböző fajta számok kezelése futási időben történik, és egy típusként kezelendők. A bool típusnak kétfajta értéke lehet, a True, és a False. A char típus az ASCII karakterkészletet veheti fel értékül, a karakterkonstansokat sima aposztrófok közé írjuk, a speciális jeleket C-vel azonos módon jelöljük, például: 'a', '$', '\n' stb.

Ha T egy típus, akkor [T] a T típusú elemeket tartalmazó listák típusa. Például [[1,2],[2,3],[4,5]] típusa [[num]], azaz num-listák listája. A string konstansok [char] típusúak, azaz például egy "hello" string rövidített formája a ['h','e','l','l','o'] stringnek.
Ha T1 es Tn típusok, akkor (T1,...,Tn) az olyan tuple-k típusa melyek ilyen típusú elemeket tartalmaznak. Például a (True,"hello",36) típusa (bool,[char],num).
Ha T1 es T2 típusok, akkor T1->T2 azon függvények típusa, melyek T1 argumentumokkal rendelkeznek és T2 típusú az eredményük. Például a példaként már említett sum függvény [num]->num típusú, a quadsolve függvény pedig num->num->[num] típusú. (Megjegyzendő, hogy a -> jobb asszociatív)

A Miranda script-ek tartalmazhatnak típusdeklarációkat. Ezekben :: jelzi, hogy a baloldala jobboldali típusból való. Például

sq:: num->num    || négyzetreemelés
sq n = n*n

ident:: num->num    || identitás
ident x = x

inc:: num->num    || inkrementálás
inc x = x+1

sqinc:: num->num
sqinc x = sq (inc x)

fac:: num->num    || faktoriális
fac x = cond (x=0) 1 (x * fac x-1)


reverse [] = []
reverse (a:as) = reverse as ++ [a]

Ezt a függvényt karakterlistára alkalmazva eredményül szintén egy karakterekből álló listát kapunk, melyben a szöveg megfordítva található. Ha számokból álló listára alkalmazzuk, akkor azt is megfordítja. Nagyon jó lenne, ha a típusrendszer engedné alkalmazni az ilyen típusú függvényeket különböző fajtájú listákra is. A Miranda rendszere megengedi az ilyen típusdefiníciót, a következőképpen:

reverse:: [*]->[*]

ami azt jelenti, hogy argumentumként listákat fogad el, melyeknek elemei tetszôleges típusúak, és egy olyan listát ad eredményül, mely elemeinek típusa az argumentum elemeinek típusával egyezik.
A tetszőleges típusok jelölésére vannak az ún. általános típusváltozók, melyeket a *, **, ***, ... szimbólumokkal jelölünk. Egy változónév többször is előfordulhat egy típusdefinícióban, ilyen esetben az azonos név előfordulása azonos típust jelent. Nem egyező nevek csak olyan típust indukálnak, melyek nem azonosak. Ha a típusváltozó előfordul a típusdefinícióban, akkor a függvényt polimorf, vagy általános függvénynek nevezzük.
Például az identitás-függvény Mirandában:

id x = x

alakú és

id:: *->*

típusú. Azaz az identitás-függvény sokféle konkrét típusú lehet, nevezetesen minden olyan típus illeszkedik rá amelyben a *-ot konkrét típusra cseréljük. Például num->num, bool->bool.
Miranda típus-szerkezete (néhány korábban definiált példa típusa):

ack:: num->num->num
sum:: [num]->num
month:: [char]->bool
fst:: (*,**)->*
snd:: (*,**)->**
foldr:: (*->**->**)->**->[*]->**
perms:: [*]->[[*]]