Миранда (язык программирования) - Miranda (programming language)
Парадигма | ленивый , функциональный , декларативный |
---|---|
Разработано | Дэвид Тернер |
Разработчик | Research Software Ltd |
Впервые появился | 1985 г. |
Печатная дисциплина | сильный , статичный |
Веб-сайт | miranda |
Основные реализации | |
Миранда | |
Под влиянием | |
KRC , ML , SASL , Надежда | |
Под влиянием | |
Чистый , Хаскелл , Оруэлл , Microsoft Power Fx |
Miranda - это ленивый , чисто функциональный язык программирования, разработанный Дэвидом Тернером в качестве преемника его более ранних языков программирования SASL и KRC , с использованием некоторых концепций ML и Hope . Он был разработан английской компанией Research Software Ltd. (владеющей торговой маркой Miranda ) и стал первым чисто функциональным языком, получившим коммерческую поддержку.
Miranda была впервые выпущена в 1985 году как быстрый интерпретатор на языке C для операционных систем со вкусом Unix , с последующими выпусками в 1987 и 1989 годах. Она оказала сильное влияние на более поздний язык программирования Haskell .
Обзор
Миранда - ленивый , чисто функциональный язык программирования. То есть в нем отсутствуют побочные эффекты и функции обязательного программирования . Программа Miranda (называемая скриптом ) - это набор уравнений, которые определяют различные математические функции и алгебраические типы данных . Здесь важен набор слов : порядок уравнений, как правило, не имеет значения, и нет необходимости определять объект до его использования.
Поскольку алгоритм синтаксического анализа интеллектуально использует макет (отступ), редко требуется заключать в скобки операторы и не требуются терминаторы операторов. Эта функция, вдохновленная ISWIM , также используется в occam и Haskell, а позже была популяризирована Python .
Комментарий вводится персонажами в обычный сценарий ||
и продолжается до конца той же строки. Альтернативное соглашение о комментировании влияет на весь файл исходного кода, известное как « грамотный сценарий », в котором каждая строка считается комментарием, если она не начинается со >
знака.
Основные Миранды типы данных являются char
, num
и bool
. Символьная строка - это просто список char
, num
который незаметно преобразуется между двумя базовыми формами: целыми числами произвольной точности (также известными как bignums) по умолчанию и обычными значениями с плавающей запятой по мере необходимости.
Кортежи - это последовательности элементов потенциально смешанных типов, аналогичные записям в языках, подобных Pascal , и записываются в скобках:
this_employee = ("Folland, Mary", 10560, False, 35)
Список вместо наиболее часто используется структура данных в Миранде. Он пишется в квадратных скобках и с элементами, разделенными запятыми, и все они должны быть одного типа:
week_days = ["Mon","Tue","Wed","Thur","Fri"]
Объединение списков ++
, вычитание --
, построение :
, размер #
и индексирование !
, поэтому:
days = week_days ++ ["Sat","Sun"]
days = "Nil":days
days!0
⇒ "Nil"
days = days -- ["Nil"]
#days
⇒ 7
Существует несколько ярлыков для создания ..
списков : используется для списков, элементы которых образуют арифметический ряд, с возможностью указания приращения, отличного от 1:
fac n = product [1..n]
odd_sum = sum [1,3..100]
Более общие и мощные средства построения списков предоставляются « списками » (ранее известными как «выражения ZF»), которые бывают двух основных форм: выражение, применяемое к ряду терминов, например:
squares = [ n * n | n <- [1..] ]
(который читается: список n в квадрате, где n берется из списка всех положительных целых чисел) и ряд, в котором каждый член является функцией предыдущего, например:
powers_of_2 = [ n | n <- 1, 2*n .. ]
Как следует из этих двух примеров, Миранда допускает списки с бесконечным числом элементов, самый простой из которых - список всех положительных целых чисел: [1..]
Обозначения для применения функции просто сопоставлены, как в sin x
.
В Миранде, как и в большинстве других чисто функциональных языков, функции являются первоклассными гражданами, то есть они могут быть переданы в качестве аргументов другим функциям, возвращены как результаты или включены как элементы структур данных. Более того, функция с двумя или более параметрами может быть «частично параметризована» или каррирована путем предоставления меньшего количества аргументов, чем полное количество параметров. Это дает другую функцию, которая с учетом остальных параметров вернет результат. Например:
add a b = a + b
increment = add 1
- это обходной способ создания функции «приращение», которая добавляет единицу к своему аргументу. На самом деле, add 4 7
принимает двухпараметрическую функцию add
, применяет ее к 4
получению однопараметрической функции, которая добавляет четыре к своему аргументу, а затем применяет это к 7
.
Любую функцию с двумя параметрами (операндами) можно превратить в инфиксный оператор (например, учитывая определение add
функции, приведенное выше, этот термин $add
во всех отношениях эквивалентен +
оператору), и каждый инфиксный оператор, принимающий два параметра, может быть превращен в соответствующая функция. Таким образом:
increment = (+) 1
это кратчайший способ создать функцию, которая добавляет единицу к своему аргументу. Точно так же в
half = (/ 2)
reciprocal = (1 /)
генерируются две однопараметрические функции. Интерпретатор понимает в каждом случае, какой из двух параметров оператора деления предоставляется, давая функции, которые соответственно делят число на два и возвращают его обратное.
Хотя Miranda является языком программирования со строгой типизацией , он не требует явного объявления типов . Если тип функции , является явно не объявлен, интерпретатор выводит его из вида его параметров и как они используются в функции. В дополнении к основным типам ( char
, num
, bool
), она включает в себя типа «ничего» , где тип параметра не имеет значения, как и в функции списка реверсирования:
rev [] = []
rev (a:x) = rev x ++ [a]
который может быть применен к списку любого типа данных, для которого явное объявление типа функции будет:
rev :: [*] -> [*]
Наконец, он имеет механизмы для создания программных модулей и управления ими , внутренние функции которых невидимы для программ, вызывающих эти модули.
Образец кода
Следующий скрипт Миранды определяет набор всех подмножеств набора чисел.
subsets [] = [[]]
subsets (x:xs) = [[x] ++ y | y <- ys] ++ ys
where ys = subsets xs
и это грамотный сценарий для функции, primes
которая дает список всех простых чисел
> || 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]
Здесь у нас есть еще несколько примеров
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 = b + (multiply (a-1) b)
fak :: num -> num
fak 0 = 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 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) (delete (minel r) r)
delete x (N l x r) = N (delete (maxel l) l) (maxel l) r
delete x (N l w r) = N (delete x l) w (delete x r)