Миранда (язык программирования) - Miranda (programming language)

Миранда
Логотип Miranda (язык программирования) .jpg
Парадигма ленивый , функциональный , декларативный
Разработано Дэвид Тернер
Разработчик Research Software Ltd
Впервые появился 1985 г. ( 1985 )
Печатная дисциплина сильный , статичный
Веб-сайт miranda .org .uk
Основные реализации
Миранда
Под влиянием
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)

использованная литература

внешние ссылки