Miranda es un lenguaje de programación perezoso y puramente funcional diseñado por David Turner como sucesor de sus lenguajes de programación anteriores SASL y KRC , utilizando algunos conceptos de ML y Hope . Fue producido por Research Software Ltd. de Inglaterra (que tiene una marca comercial con el nombre Miranda ) y fue el primer lenguaje puramente funcional que recibió soporte comercial. [ cita requerida ]
Paradigma | perezoso , funcional , declarativo |
---|---|
Diseñada por | David Turner |
Desarrollador | Research Software Ltd |
Apareció por primera vez | 1985 |
Disciplina de mecanografía | fuerte , estático |
Sitio web | miranda |
Implementaciones importantes | |
Miranda | |
Influenciado por | |
KRC , ML , SASL , esperanza | |
Influenciado | |
Limpio , Haskell , Orwell , Microsoft Power Fx |
Miranda fue lanzado por primera vez en 1985, como intérprete rápido en C para sistemas operativos Unix- Flavour, con lanzamientos posteriores en 1987 y 1989. Miranda tuvo una fuerte influencia en el lenguaje de programación Haskell posterior . [1]
Descripción general
Miranda es un lenguaje de programación perezoso y puramente funcional . Es decir, carece de efectos secundarios y funciones de programación imperativas . Un programa de Miranda (llamado script ) es un conjunto de ecuaciones que definen varias funciones matemáticas y tipos de datos algebraicos . La palabra conjunto es importante aquí: el orden de las ecuaciones es, en general, irrelevante y no es necesario definir una entidad antes de su uso.
Dado que el algoritmo de análisis hace un uso inteligente del diseño (sangría), rara vez es necesario colocar entre corchetes las declaraciones y no se requieren terminadores de declaraciones. Esta característica, inspirada en ISWIM , también se usa en occam y Haskell y luego fue popularizada por Python .
Los personajes introducen los comentarios en los guiones regulares ||
y continúan hasta el final de la misma línea. Una convención alternativa de comentarios afecta a todo un archivo de código fuente, conocido como " escritura alfabetizada ", en la que cada línea se considera un comentario a menos que comience con un >
signo.
Los tipos de datos básicos de Miranda son char
, num
y bool
. Una cadena de caracteres es simplemente una lista de char
, mientras que num
se convierte silenciosamente entre dos formas subyacentes: enteros de precisión arbitraria (también conocidos como bignums) de forma predeterminada y valores de punto flotante regulares según sea necesario.
Las tuplas son secuencias de elementos de tipos potencialmente mixtos, análogas a los registros en lenguajes similares a Pascal , y se escriben delimitadas entre paréntesis:
this_employee = ( "Folland, Mary" , 10560 , False , 35 )
En cambio, la lista es la estructura de datos más utilizada en Miranda. Está escrito delimitado por corchetes y con elementos separados por comas, todos los cuales deben ser del mismo tipo:
week_days = [ "Mon" , "Tue" , "Wed" , "Thur" , "Fri" ]
La concatenación de la lista es ++
, la resta es --
, la construcción es :
, el tamaño es #
y la indexación es !
, entonces:
days = week_days ++ [ "Sáb" , "Dom" ] days = "Nil" : días dias ! 0 ⇒ "Nulo" días = días - [ "Nil" ] # días ⇒ 7
Existen varios atajos de construcción ..
de listas : se utiliza para listas cuyos elementos forman una serie aritmética, con la posibilidad de especificar un incremento distinto de 1:
fac n = producto [ 1 .. n ] impar_sum = suma [ 1 , 3 .. 100 ]
Las " listas por comprensión " (anteriormente conocidas como "expresiones ZF") proporcionan facilidades de creación de listas más generales y potentes : una expresión aplicada a una serie de términos, por ejemplo:
cuadrados = [ n * n | n <- [ 1 .. ] ]
(que se lee: lista de n al cuadrado donde n se toma de la lista de todos los enteros positivos) y una serie donde cada término es una función del anterior, por ejemplo:
poderes_de_2 = [ n | n <- 1 , 2 * n .. ]
Como implican estos dos ejemplos, Miranda permite listas con un número infinito de elementos, de los cuales el más simple es la lista de todos los enteros positivos: [1..]
La notación para la aplicación de funciones es simplemente yuxtaposición, como en sin x
.
En Miranda, como en la mayoría de los otros lenguajes puramente funcionales, las funciones son ciudadanos de primera clase , es decir, pueden pasarse como argumentos a otras funciones, devolverse como resultados o incluirse como elementos de estructuras de datos. Es más, una función con dos o más parámetros puede ser "parcialmente parametrizada", o currizada , proporcionando menos argumentos que el número total de parámetros. Esto da otra función que, dados los parámetros restantes, devolverá un resultado. Por ejemplo:
agregar a b = a + b incremento = agregar 1
es una forma indirecta de crear una función "incremento" que agrega uno a su argumento. En realidad, add 4 7
toma la función de dos parámetros add
, la aplica para 4
obtener una función de un solo parámetro que suma cuatro a su argumento y luego la aplica a 7
.
Cualquier función con dos parámetros (operandos) se puede convertir en un operador infijo (por ejemplo, dada la definición de la add
función anterior, el término $add
es en todos los sentidos equivalente al +
operador) y cada operador infijo que toma dos parámetros se puede convertir en un función correspondiente. Por lo tanto:
incremento = ( + ) 1
es la forma más breve de crear una función que agrega una a su argumento. Del mismo modo, en
mitad = ( / 2 ) recíproco = ( 1 / )
se generan dos funciones de un solo parámetro. El intérprete comprende en cada caso cuál de los dos parámetros del operador de división se está suministrando, dando funciones que respectivamente dividen un número por dos y devuelven su recíproco.
Aunque Miranda es un lenguaje de programación fuertemente tipado , no insiste en declaraciones de tipo explícitas . Si el tipo de una función no se declara explícitamente, el intérprete lo infiere del tipo de sus parámetros y cómo se utilizan dentro de la función. Además de los tipos básicos ( char
, num
, bool
), que incluye un tipo de "nada", donde el tipo de un parámetro no importa, como en la función de lista de reversión de:
rev [] = [] rev ( a : x ) = rev x ++ [ a ]
que se puede aplicar a una lista de cualquier tipo de datos, para lo cual la declaración explícita del tipo de función sería:
rev :: [ * ] -> [ * ]
Finalmente, tiene mecanismos para crear y administrar módulos de programa cuyas funciones internas son invisibles para los programas que llaman a esos módulos.
Código de muestra
El siguiente script de Miranda determina el conjunto de todos los subconjuntos de un conjunto de números
subconjuntos [] = [ [] ] subconjuntos ( x : xs ) = [[ x ] ++ y | y <- ys ] ++ ys donde ys = subconjuntos xs
y este es un script alfabetizado para una función primes
que da la lista de todos los números primos
> || La lista infinita de todos los números primos.La lista de números primos potenciales comienza con todos los números enteros a partir del 2; a medida que se devuelve cada primo, todos los siguientes números que pueden dividirse exactamente por él se filtran de la lista de candidatos.> primos = tamiz [2 ..] > tamiz (p: x) = p: tamiz [n | n <- x; n mod p ~ = 0]
Aquí tenemos algunos ejemplos más.
max2 :: num -> num -> num max2 a b = a , si a > b = b , en caso contrariomax3 :: num -> num -> num -> num max3 a b c = max2 ( max2 a b ) ( max2 a c )multiplicar :: num -> num -> num multiplicar 0 b = 0 multiplicar a b = b + ( multiplicar ( a - 1 ) b )fak :: num -> num fak 0 = 1 fak n = n * ( fak n - 1 )número de artículo :: [ * ] -> num número de artículo [] = 0 número de artículo ( a : x ) = 1 + número de artículo xdía de la semana :: = Mo | Tu | Nosotros | Th | Fr | Sa | SuisWorkDay :: weekday -> bool isWorkDay Sa = False isWorkDay Su = False isWorkDay anyday = Trueárbol * :: = E | N ( árbol * ) * ( árbol * )recuento de nodos :: árbol * -> num recuento de nodos E = 0 recuento de nodos ( N l w r ) = recuento de nodos l + 1 + recuento de nodos rcuenta vacía :: árbol * -> num cuenta vacía E = 1 cuenta vacía ( N l w r ) = cuenta vacía l + cuenta vacía rárbol Ejemplo = N ( N ( N E 1 E ) 3 ( N E 4 E )) 5 ( N ( N E 6 E ) 8 ( N E 9 E )) día de la semana Árbol = N ( N ( N E Mo E ) Tu ( N E We E )) Th ( N ( N E Fr E ) Sa ( N E Su ))insertar :: * -> calle * -> calle * insertar x E = N E x E insertar x ( N l w E ) = N l w x insertar x ( N E w r ) = N x w r insertar x ( N l w r ) = insertar x l , si x < w = insertar x r , de lo contrariolist2searchtree :: [ * ] -> árbol * list2searchtree [] = E list2searchtree [ x ] = N E x E list2searchtree ( x : xs ) = insertar x ( list2searchtree xs )maxel :: árbol * -> * maxel E = error "vacío" maxel ( N l w E ) = w maxel ( N l w r ) = maxel rminel :: árbol * -> * minel E = error "vacío" minel ( N E w r ) = w minel ( N l w r ) = minel l|| Atravesando: ir a través de los valores de árbol , poner ellos en la listapreorden , inorder , postorder :: árbol * -> [ * ] inorder E = [] inorder N l w r = inorder l ++ [ w ] ++ inorder rpreorden E = [] preorden N l w r = [ w ] ++ preorden l ++ preorden rpostorder E = [] postorder N l w r = postorder l ++ postorder r ++ [ w ]altura :: árbol * -> num altura E = 0 altura ( N l w r ) = 1 + max2 ( altura l ) ( altura r )cantidad :: num -> num cantidad x = x , si x > = 0 cantidad x = x * ( - 1 ), de lo contrarioy :: bool -> bool -> bool y Verdadero Verdadero = Verdadero y x y = False|| Un AVL - Tree es un árbol donde la diferencia entre los nodos secundarios no es mayor que 1 || i todavía tengo que probar esto isAvl :: árbol * -> bool isAvl E = True isAvl ( N l w r ) = y ( isAvl l ) ( isAvl r ), si cantidad (( nodecount l ) - ( nodecount r )) < 2 = False , de lo contrario borrar :: * -> árbol * -> árbol * borrar x E = E borrar x ( N E x E ) = E borrar x ( N E x r ) = N E ( minel r ) ( borrar ( minel r ) r ) borrar x ( N l x r ) = N ( borrar ( maxel l ) l ) ( maxel l ) r borrar x ( N l w r ) = N ( borrar x l ) w ( borrar x r )
Referencias
- ^ Hudak, Paul; Hughes, John (2007). "Una historia de Haskell: ser vago con la clase" .
enlaces externos
- Página web oficial