Miranda (linguaggio di programmazione)

Da Wikipedia, l'enciclopedia libera.
Template-info.svg

Miranda è un linguaggio di programmazione puramente funzionale sviluppato da David Turner come successore dei suoi precedenti linguaggi di programmazione SASL e KRC utilizzando alcuni concetti di ML ed Hope. Commercializzato dalla Research Software Ltd. of England, di cui la parola "Miranda" è un marchio di fabbrica, è stato il primo linguaggio funzionale destinato ad un uso commerciale invece che solo accademico.

La soluzione di molti problemi di esempio è più breve e semplice in Miranda che nella maggior parte degli altri diffusi linguaggi di programmazione, con la possibile eccezione dell'APL, e, come per altri linguaggi funzionali, i suoi utenti riferiscono di poter produrre programmi più affidabili con cicli di sviluppo più brevi rispetto a quelli dei linguaggi imperativi usati in precedenza.

È stato pubblicato nel 1985, ed è stato scritto per esso (in linguaggio C) un solo interprete per sistemi Unix. Haskell, un linguaggio sviluppato successivamente, è simile per molti versi a Miranda.

Descrizione[modifica | modifica sorgente]

Miranda è un linguaggio lazy puramente funzionale, cioè non ha funzionalità di programmazione imperativa ed effetti collaterali.

Un programma Miranda (chiamato anche script) è un insieme di equazioni che definiscono varie funzioni matematiche e tipi di dati algebrici. La parola insieme è importante, in questo contesto: l'ordine in cui vengono elencate le equazioni, in generale, è irrilevante e non è necessario definire un'entità prima di usarla.

Dal momento che l'interprete fa un uso intelligente dell'indentazione, c'è raramente bisogno di definizioni tra parentesi e non servono segni terminali di definizioni. questa caratteristica è presente anche nei linguaggi di programmazione Occam e Haskell ed è stata resa popolare da Python.

Parti di commento sono introdotte in normali righe con i caratteri || e continuano fino alla fine della stessa riga. Un tipo convenzionale di commento alternativo riguarda un intero file di codice sorgente, chiamato script letterato, in cui ogni riga è considerata un commento a meno che non inizi con un segno di >.

I tipi di dati fondamentali in Miranda sono caratteri, numeri e simboli. Una stringa di caratteri è semplicemente una lista di caratteri, mentre un numero viene convertito di nascosto in due forme fondamentali: interi a precisione infinita per default e valori a virgola mobile se richiesto.

Le tuple sono sequenze di tipo potenzialmente misto, analoghe ai record nei linguaggi di tipo Pascal, e vengono scritte tra parentesi:

   questo_impiegato = ("Follanda, Maria", 10560, False, 35)

La lista, list, è invece la struttura di dati più spesso usata in Miranda. Viene scritta tra parentesi quadre e con elementi separati da virgole e tutti dello stesso tipo:

 giorni_settimana = ["Lun","Mar","Mer","Gio","Ven"] 

La concatenazione di liste è ++, la sottrazione è --, La costruzione è :, il dimensionamento è # e l'indicizzazione è !, perciò:

 giorni = giorni_settimana ++ ["Sab","Dom"]
 giorni = "Nil":giorni
 giorni!0
-> "Nil"
 giorni= giorni--["Nil"]
-> 7

Ci sono diverse scorciatoie per la costruzione delle liste: .. viene usato per le liste i cui elementi formano una serie aritmetica, con la possibilità di specificare un incremento diverso da 1:

 fac n   = product [1..n]
 odd_sum = sum [1,3..100]

Aiuti più generali e potenti per la costruzione delle liste sono forniti dalla "conoscenza delle liste" (prima chiamate "espressioni ZF"), che si presentano in due forme: un'espressione applicata ad una serie di termini, ad esempio:

 squares = [ n * n | n <- [1..] ]

(che si legge: una lista di n al quadrato dove n è preso dalla lista di tutti gli interi positivi)

e una serie in cui ciascun termine è funziione del precedente, ad esempio:

 powers_of_2 = [ n | n <- 1, 2*n .. ]

Come si deduce da questi due esemp, Miranda consente l'uso di liste con un numero infinito di elementi, la più semplice delle quali è la lista degli interi positivi: [1..].

La notazione per applicare la funzione è la semplice giustapposizione come in sin x. In Miranda, come in molti altri linguaggi puramente funzionali, le funzioni sono cittadini di prima classe, vale a dire che possono essere assegnate come parametri ad altre funzioni, ottenute come risultati o incluse come elementi in strutture di dati. Ciò che è più importante, una funzione che richiede due o più parametri può essere "parzialmente parametrizzata" fornendole un numero inferiore dei parametri complessivi. Ciò crea un'altra funzione che, dati i restanti parametri, fornirà il risultato. Per esempio:

 add a b = a + b
 increment = add 1

è un modo indiretto di creare una funzione "incremento" che aggiunge 1 al suo argomento. In realtà, add 4 7 prende la funzione a due parametri add, la applica a 4 ottenendo una funzione a un solo parametro che aggiunge 4 al suo argomento, quindi la applica a 7.

Qualsiasi funzione con due parametri può essere trasformata in un operatore infisso (per esempio, data la definizione della funzione precedente add, il termine $add è in tutto e per tutto equivalente ell'operatore +) e ogni operatore infisso con due parametri può essere trasformato nella corrispondente funzione.

Così:

 increment = (+) 1

è il modo più rapido di creare una funzione che aggiunge 1 al suo argomento.

In maniera simile, in

 half = (/ 2)
 reciprocal = (1 /)

vengono generate due funzioni con un solo parametro. L'interprete capisce in ognuno dei due casi quale parametro tra i due operatori di divisione venga fornito e crea le funzioni che rispettivamente dividono ubn numero in due e restituiscono il suo reciproco.

Benché Miranda sia un linguaggio fortemente basato sui modelli, non esige dichiarazioni esplicite di modello. Se un tipo di funzione non viene esplicitamente dichiarata, l'interprete la inferisce dal tipo dei suoi parametri e dal modo in cui vengono usati nella funzione. In aggiunta ai tipi fondamentali, caratteri, numeri, simboli, il linguaggio include un tipo "qualsiasi" in cui il tipo di parametro non ha importanza, come nella funzione che inverte una lista:

 rev [] = []
 rev (a:x) = rev x ++ [a]

che può essere applicata a una lista con qualsiasi tipo di dato, per cui la dichiarazione esplicita del tipo di funzione sarebbe:

 rev :: [*] -> [*]

Infine, il linguaggio possiede meccanismi per creare e gestire moduli di programma le cui funzioni interne sono invisibili ai programmi che chiamano quei moduli.

Esempi di programmi Miranda[modifica | modifica sorgente]

Il seguente script Miranda determina l'insieme di tutti i sottoinsiemi di un insieme di numeri

  subsets []     = [[]]
  subsets (x:xs) = [[x] ++ y | y <- ys] ++ ys
                   where ys = subsets xs

e questo è un literate script per una funzione primes che fornisce la lista di tutti i numeri primi

  >|| La lista infinita di tutti i numeri primi, usando il crivello di Eratostene.
  
  La lista dei potenziali numeri primi inizia con la lista dei numeri interi dal due in avanti; 
  dopo che è stato restituito ciascun numero primo,tutti i numeri che possono essere divisi in 
  modo esatto per esso vengono eliminati dalla lista dei candidati.
   
  > primes = sieve [2..]
  > sieve (p:x) = p : sieve [n | n <- x; n mod p ~= 0]

Collegamenti esterni[modifica | modifica sorgente]