This article includes a list ofgeneral references, butit lacks sufficient correspondinginline citations. Please help toimprove this article byintroducing more precise citations.(September 2016) (Learn how and when to remove this message) |
| Miranda | |
|---|---|
| Paradigm | lazy,functional,declarative |
| Designed by | David Turner |
| Developer | Research Software Ltd |
| First appeared | 1985; 40 years ago (1985) |
| Stable release | |
| Typing discipline | strong,static |
| License | 2-clause BSD License[2] |
| Website | miranda |
| Majorimplementations | |
| Miranda | |
| Influenced by | |
| KRC,ML,SASL,Hope | |
| Influenced | |
| Clean,Haskell,Orwell,Microsoft Power Fx | |
Miranda is alazy,purely functionalprogramming language designed byDavid Turner as a successor to his earlier programming languagesSASL andKRC, using some concepts fromML andHope. It was produced by Research Software Ltd. of England (which holds a trademark on the nameMiranda)[3] and was the first purely functional language to be commercially supported.[citation needed]
Miranda was first released in 1985 as a fast interpreter inC forUnix-flavour operating systems, with subsequent releases in 1987 and 1989. It had a strong influence on the laterHaskell language.[4] Turner stated that the benefits of Miranda over Haskell are: "Smaller language, simpler type system, simpler arithmetic".[5]
In 2020 a version of Miranda was released as open source under aBSD licence. The code has been updated to conform to modern C standards (C11/C18) and to generate 64-bit binaries. This has been tested on operating systems includingDebian,Ubuntu,WSL/Ubuntu, andmacOS (Catalina).[5][6]

The nameMiranda is taken from the gerundive form of the latin verbmiror,[7] meaning "to be admired".
The logo features a rendition byJohn William Waterhouse of the characterMiranda from Shakespeare'sThe Tempest.
Miranda is alazy,purely functional programming language. That is, it lacksside effects andimperative programming features. A Miranda program (called ascript) is a set ofequations that define various mathematicalfunctions andalgebraic data types. The wordset is important here: the order of the equations is, in general, irrelevant, and there is no need to define an entity prior to its use.
Since theparsing algorithm makes intelligent use of layout (indentation, viaoff-side rule), bracketing statements are rarely needed and statement terminators are unneeded. This feature, inspired byISWIM, is also used inoccam andHaskell and was later popularized byPython.
Commentary is introduced into regular scripts by the characters|| and continue to the end of the same line. An alternative commenting convention affects an entire source code file, known as a "literate script", in which every line is considered a comment unless it starts with a> sign.
Miranda's basicdata types arechar,num andbool. A character string is simply a list ofchar, whilenum is silently converted between two underlying forms:arbitrary-precision integers (a.k.a. bignums) by default, and regularfloating point values as required.
Tuples are groups of elements of potentially mixed types, in a fixed order, analogous torecords inPascal-like languages, but with unnamed fields. They are delimited with parentheses:
this_employee=("Folland, Mary",10560,False,35)
Thelist instead is the most commonly used data structure in Miranda. It is written delimited by square brackets and with comma-separated elements, all of which must be of the same type:
week_days=["Mon","Tue","Wed","Thur","Fri"]
List concatenation is++, subtraction is--, construction is:, sizing is# and indexing is!, so:
days=week_days++["Sat","Sun"]days="Nil":daysdays!0⇒"Nil"days=days--["Nil"]#days⇒7
There are several list-building shortcuts:.. is used for lists whose elements form an arithmetic series, with the possibility for specifying an increment other than 1:
facn=product[1..n]odd_sum=sum[1,3..100]
More general and powerful list-building facilities are provided by "list comprehensions" (previously known as "ZF expressions"), which come in two main forms: an expression applied to a series of terms, e.g.:
squares=[n*n|n<-[1..]]
(which is read: list of n squared where n is taken from the list of all positive integers) and a series where each term is a function of the previous one, e.g.:
powers_of_2=[n|n<-1,2*n..]
As these two examples imply, Miranda allows for lists with an infinite number of elements, of which the simplest is the list of all positive integers:[1..]
The notation for function application is simply juxtaposition, as insin x.
In Miranda, as in most other purely functional languages, functions arefirst-class citizens, which is to say that they can be passed asarguments to other functions, returned as results, or included as elements of data structures. What is more, a function with two or more parameters may be "partially parameterised", orcurried, by supplying fewer arguments than the full number of parameters. This gives another function which, given the remaining parameters, will return a result. For example:
addab=a+bincrement=add1
is a roundabout way of creating a function "increment" which adds one to its argument. In reality,add 4 7 takes the two-parameter functionadd, applies it to4 obtaining a single-parameter function that adds four to its argument, then applies that to7.
Any function with two parameters (operands) can be turned into an infix operator (for example, given the definition of theadd function above, the term$add is in every way equivalent to the+ operator) and every infix operator taking two parameters can be turned into a corresponding function.Thus:
increment=(+)1
is the briefest way to create a function that adds one to its argument. Similarly, in
half=(/2)reciprocal=(1/)
two single-parameter functions are generated. The interpreter understands in each case which of the divide operator's two parameters is being supplied, giving functions which respectively divide a number by two and return its reciprocal.
Although Miranda is astrongly typed programming language, it does not insist on explicit typedeclarations. If a function's type is not explicitly declared, the interpreterinfers it from the type of its parameters and how they are used within the function. In addition to the basic types (char,num,bool), it includes an "anything" type where the type of a parameter does not matter, as in the list-reversing function:
rev[]=[]rev(a:x)=revx++[a]
which can be applied to a list of any data type, for which the explicit function type declaration would be:
rev::[*]->[*]
Finally, it has mechanisms for creating and managing programmodules whose internal functions are invisible to programs calling those modules.
The following Miranda script determines the set of all subsets of a set of numbers
subsets[]=[[]]subsets(x:xs)=[[x]++y|y<-ys]++yswhereys=subsetsxs
and this is a literate script for a functionprimeswhich gives the list of all prime numbers
> || 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 bedivided 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]
Here, we have some more examples
max2::num->num->nummax2ab=a,ifa>b=b,otherwisemax3::num->num->num->nummax3abc=max2(max2ab)(max2ac)multiply::num->num->nummultiply0b=0multiplyab=b+(multiply(a-1)b)fak::num->numfak0=1fakn=n*fak(n-1)itemnumber::[*]->numitemnumber[]=0itemnumber(a:x)=1+itemnumberxweekday::=Mo|Tu|We|Th|Fr|Sa|SuisWorkDay::weekday->boolisWorkDaySa=FalseisWorkDaySu=FalseisWorkDayanyday=Truetree*::=E|N(tree*)*(tree*)nodecount::tree*->numnodecountE=0nodecount(Nlwr)=nodecountl+1+nodecountremptycount::tree*->numemptycountE=1emptycount(Nlwr)=emptycountl+emptycountrtreeExample=N(N(NE1E)3(NE4E))5(N(NE6E)8(NE9E))weekdayTree=N(N(NEMoE)Tu(NEWeE))Th(N(NEFrE)Sa(NESu))insert::*->stree*->stree*insertxE=NExEinsertx(NlwE)=Nlwxinsertx(NEwr)=Nxwrinsertx(Nlwr)=insertxl,ifx<w=insertxr,otherwiselist2searchtree::[*]->tree*list2searchtree[]=Elist2searchtree[x]=NExElist2searchtree(x:xs)=insertx(list2searchtreexs)maxel::tree*->*maxelE=error"empty"maxel(NlwE)=wmaxel(Nlwr)=maxelrminel::tree*->*minelE=error"empty"minel(NEwr)=wminel(Nlwr)=minell||Traversing:goingthroughvaluesoftree,puttingtheminlistpreorder,inorder,postorder::tree*->[*]inorderE=[]inorderNlwr=inorderl++[w]++inorderrpreorderE=[]preorderNlwr=[w]++preorderl++preorderrpostorderE=[]postorderNlwr=postorderl++postorderr++[w]height::tree*->numheightE=0height(Nlwr)=1+max2(heightl)(heightr)amount::num->numamountx=x,ifx>=0amountx=x*(-1),otherwiseand::bool->bool->boolandTrueTrue=Trueandxy=False||AAVL-Treeisatreewherethedifferencebetweenthechildnodesisnothigherthan1||istillhavetotestthisisAvl::tree*->boolisAvlE=TrueisAvl(Nlwr)=and(isAvll)(isAvlr),ifamount((nodecountl)-(nodecountr))<2=False,otherwisedelete::*->tree*->tree*deletexE=Edeletex(NExE)=Edeletex(NExr)=NE(minelr)(delete(minelr)r)deletex(Nlxr)=N(delete(maxell)l)(maxell)rdeletex(Nlwr)=N(deletexl)w(deletexr)