Miranda (limbaj de programare)
Miranda | |
Paradigmă | lazy, funcțională, declarativă |
---|---|
Apărut în | 1985 |
Proiectat de | David Turner |
Dezvoltator | Research Software Ltd |
Ultima versiune | 2.066[1] |
Tipare | strong, static |
Implementări majore | Miranda |
Influențat de | KRC, ML, SASL, Hope |
Influențe | Clean, Haskell |
Prezență online | miranda.org.uk |
Modifică date / text |
Miranda este un limbaj de programare leneș, pur funcțional, proiectat de David Turner ca succesor al limbajelor de programare anterioare SASL și KRC, folosind câteva concepte din ML și Hope. A fost produs de Research Software Ltd. din Anglia (care deține o marcă comercială pe numele Miranda) și a fost primul limbaj pur funcțional care trebuie susținut comercial.
Miranda a fost lansată pentru prima dată în 1985, interpretată rapid în C pentru sistemele de operare în Unix, cu lansări ulterioare în 1987 și 1989. Miranda a avut o influență puternică asupra limbajului de programare Haskell ulterior.[2]
Prezentare generală
modificareMiranda este un limbaj de programare leneș, pur funcțional. Aceasta înseamnă că nu are efecte secundare și caracteristici imperative de programare. Un program Miranda (numit script) este un set de ecuații care definesc diferite funcții matematice și tipuri de date algebrice. Setul de cuvinte este important aici: ordinea ecuațiilor este în general, irelevantă și nu este nevoie să se definească o entitate înainte de a fi utilizată.
Deoarece algoritmul de parsare utilizează inteligent aspectul (indentare), este rareori nevoie de instrucțiuni de bracketing și nu sunt necesare terminatoare de instrucțiuni. Această caracteristică, inspirată de ISWIM, este de asemenea folosită în occam și Haskell și a fost ulterior popularizată de Python.
Comentariul este introdus în scripturi obișnuite de caracterele ||
și continuați până la sfârșitul aceleiași linii. O convenție alternativă de comentare afectează un întreg fișier de cod sursă, cunoscut sub numele de "scenariu literat", în care fiecare linie este considerată un comentariu dacă nu începe cu un semn >
.
Tipurile de date de bază ale lui Miranda sunt char
, num
și bool
. Un șir de caractere este pur și simplu o listă de caractere char
, în timp ce num
este convertit în tăcere între două forme subiacente: numerele de precizie arbitrară (a.k.a.bignums) implicit și valorile punctului de flotare obișnuite, după cum este necesar.
Tupele sunt secvențe de elemente de tipuri mixte potențiale, similare cu înregistrările din limbile asemănătoare cu Pascal și sunt scrise cu paranteze:
this_employee = ("Folland, Mary", 10560, False, 35)
În schimb, lista este cea mai frecvent utilizată structură de date din Miranda. Este scrisă delimitată de paranteze pătrate și elemente separate prin virgulă, toate acestea trebuie să fie de același tip:
week_days = ["Mon","Tue","Wed","Thur","Fri"]
Listă de concatenare este ++
, scăderea este --
, construcția este :
, dimensionarea este #
și indexarea este!
, Deci:
days = week_days ++ ["Sat","Sun"]
days = "Nil":days
days!0
⇒ "Nil"
days = days -- ["Nil"]
#days
⇒ 7
Există mai multe comenzi rapide pentru crearea listelor: ..
este folosit pentru liste ale căror elemente formează o serie aritmetică, cu posibilitatea de a specifica un increment diferit de 1:
fac n = product [1..n]
odd_sum = sum [1,3..100]
Mai multe facilități generale și puternice de construire a listelor sunt furnizate prin "înțelegeri în liste" (anterior cunoscute sub numele de "expresii ZF"), care se găsesc în două forme principale: o expresie aplicată unei serii de termeni, de exemplu:
squares = [ n * n | n <- [1..] ]
(care este citit: lista cu n pătrat unde n este luat din lista tuturor întregurilor pozitive) și o serie în care fiecare termen este o funcție a celui anterior, de exemplu:
powers_of_2 = [ n | n <- 1, 2*n .. ]
Așa cum aceste două exemple implică, Miranda permite liste cu un număr infinit de elemente, dintre care cea mai simplă este lista tuturor întregurilor pozitive: [1..]
Notația pentru aplicarea funcției este pur si simplu juxtapunere, ca în sin x
.
În Miranda, ca în majoritatea limbajelor pur funcționale, funcțiile sunt de primă clasă, adică pot fi trecute ca parametri pentru alte funcții, returnate ca rezultate sau incluse ca elemente ale structurilor de date. În plus, o funcție care necesită doi sau mai mulți parametri poate fi parțial parametrizată sau curată, furnizând mai puțin decât numărul complet de parametri. Aceasta oferă o altă funcție care, având în vedere parametrii rămași, va întoarce un rezultat. De exemplu:
add a b = a + b
increment = add 1
Orice funcție care ia doi parametri poate fi transformată într-un operator infixat (de exemplu, având în vedere definiția funcției de add
de mai sus, termenul $add
este în orice mod echivalent cu operatorul +
) și fiecare operator infix care ia doi parametri poate fi transformat în o funcție corespunzătoare.
Prin urmare:
increment = (+) 1
este cea mai scurtă modalitate de a crea o funcție care adaugă una la argumentul său. În mod similar, în
half = (/ 2)
reciprocal = (1 /)
se generează două funcții cu un singur parametru. Interpretorul înțelege în fiecare caz care dintre cei doi parametri ai operatorului de împărțire este furnizat, oferind funcții care împarte un număr cu doi și returnează inversul (reciproca).
Deși Miranda este un limbaj de programare puternic tipizat, nu insistă asupra declarațiilor de tip explicit. Dacă un tip de funcție nu este declarat explicit, interpretul îl deduce din tipul parametrilor și din modul în care sunt utilizați în cadrul funcției. În plus față de tipurile de bază (char
, num
, bool
), acesta include un tip "orice" unde tipul de parametru nu contează, ca în funcția de inversare a listei:
rev [] = []
rev (a:x) = rev x ++ [a]
care poate fi aplicată unei liste de orice tip de date, pentru care declarația de tip explicită a funcției ar fi:
rev :: [*] -> [*]
În sfârșit, dispune de mecanisme pentru crearea și gestionarea modulelor de program ale căror funcții interne sunt invizibile pentru programele care apelează la aceste module.
Cod simplu
modificareUrmătorul script Miranda determină setul tuturor subseturilor dintr-un set de numere
subsets [] = [[]]
subsets (x:xs) = [[x] ++ y | y <- ys] ++ ys
where ys = subsets xs
și acesta este un script alfabetic pentru o funcție primes
care oferă lista tuturor numerelor prime
> || The infinite list of all prime numbers.
The list of potential prime numbers starts as all integers from 2 onwards;
as each prime is returned, all the following numbers that can exactly be
divided by it are filtered out of the list of candidates.
> primes = sieve [2..]
> sieve (p:x) = p : sieve [n | n <- x; n mod p ~= 0]
Aici, avem mai multe exemple
max2 :: num -> num -> num
max2 a b = a, if a>b
= b, otherwise
max3 :: num -> num -> num -> num
max3 a b c = max2 (max2 a b) (max2 a c)
multiply :: num -> num -> num
multiply 0 b = 0
multiply a b = a + (multiply (a-1) b)
fak :: num -> num
fak 0 = 1
fak 1 = 1
fak n = n * (fak n-1)
itemnumber::[*]->num
itemnumber [] = 0
itemnumber (a:x) = 1 + itemnumber x
weekday::= Mo|Tu|We|Th|Fr|Sa|Su
isWorkDay :: weekday -> bool
isWorkDay Sa = False
isWorkDay Su = False
isWorkDay anyday = True
tree * ::= E| N (tree *) * (tree *)
nodecount :: tree * -> num
nodecount E = 0
nodecount (N l w r) = nodecount l + 1 + nodecount r
emptycount :: tree * -> num
emptycount E = 1
emptycount (N l w r) = emptycount l + emptycount r
treeExample = N ( N (N E 1 E) 3 (N E 4 E)) 5 (N (N E 6 E) 8 (N E 9 E))
weekdayTree = N ( N (N E Mo E) Tu (N E We E)) Th (N (N E Fr E) Sa (N E Su))
insert :: * -> stree * -> stree *
insert x E = N E x E
insert x (N l w E) = N l w x
insert x (N E w r) = N x w r
insert x (N l w r) = insert x l , if x <w
= insert x r , otherwise
list2searchtree :: [*] -> tree *
list2searchtree [] = E
list2searchtree [x] = N E x E
list2searchtree (x:xs) = insert x (list2searchtree xs)
maxel :: tree * -> *
maxel E = error "empty"
maxel (N l w E) = w
maxel (N l w r) = maxel r
minel :: tree * -> *
minel E = error "empty"
minel (N E w r) = w
minel (N l w r) = minel l
||Traversing: going through values of tree,putting them in list
preorder,inorder,postorder :: tree * -> [*]
inorder E = []
inorder N l w r = inorder l ++ [w] ++ inorder r
preorder E = []
preorder N l w r = [w] ++ preorder l ++ preorder r
postorder E = []
postorder N l w r = postorder l ++ postorder r ++ [w]
height :: tree * -> num
height E = 0
height (N l w r) = 1 + max2 (height l) (height r)
amount :: num -> num
amount x = x ,if x >= 0
amount x = x*(-1), otherwise
and :: bool -> bool -> bool
and True True = True
and x y = False
|| A AVL-Tree is a tree where the difference between the of the child nodes is not higher than 1
|| i still have to test this
isAvl :: tree * -> bool
isAvl E = True
isAvl (N l w r) = and (isAvl l) (isAvl r), if amount ((nodecount l) - (nodecount r)) < 2
= False, otherwise
delete :: * -> tree * -> tree *
delete x E = E
delete x (N E x E) = E
delete x (N E x r) = N E (minel r) (loeschen (minel r) r)
delete x (N l x r) = N (loeschen (maxel l) l) (maxel l) r
delete x (N l w r) = N (loeschen x l) w (loeschen x r)
Note
modificare- ^ Miranda download page (în engleză), accesat în
- ^ Hudak, Paul; Hughes, John (). „A History of Haskell: being lazy with class”.