Miranda

Mirandaは、デビッド・ターナーによって開発された遅延評価方式の純粋関数型プログラミング言語です。これは、彼が以前に開発したSASLやKRCの後継であり、MLやHopeといった他の関数型言語の影響も受けています。イギリスのリサーチ・ソフトウェア社によって販売され、商標登録もされています。

Mirandaは、研究目的だけでなく、商用利用を目指した最初の純粋関数型言語でした。この言語のコードは、特に一般的な問題を解く際に、多くの主流プログラミング言語よりも簡潔で短く記述できることが特徴です。また、他の関数型言語と同様に、命令型言語と比較して、より短期間で信頼性の高いプログラムを開発できると報告されています。

1985年に登場したMirandaの処理系は、Unix系向けのC言語で実装されたもののみが存在します。後発のHaskellは、その設計においてMirandaから多大な影響を受けています。

概要



Mirandaは、遅延評価を採用した純粋関数型言語であり、副作用がなく、命令型プログラミング機能は一切持ちません。具象構文の大きな特徴としては、オフサイドルールを採用している点が挙げられます。

コメントは `||` から行末まで、または「文芸的プログラミング」スタイルで、行頭に `>` がない行が全てコメントとして扱われます。

Mirandaの基本データ型には、`char`、`num`、`bool`があります。文字列は`char`のリストとして扱われ、`num`は内部的に多倍長整数と浮動小数点数の2つの形式を持ち、自動的に変換されます。

タプルは、異なる型のデータの順序付きコレクションで、抽象的には直積型として表現されます。


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記法とも呼ばれる)があり、2つの形式があります。式を項の列に適用する形式は以下のようになります。


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


これは、nの二乗のリストであり、nはすべての正の整数のリストから取られます。また、ある項がその1つ前の項の関数から得られる形式は次のようになります。


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


これは2のべき乗のリストです。これらの例からわかるように、Mirandaでは無限リストを表現できます。例えば、単純な無限リストの例として、すべての正の整数のリスト `[1..]` があります。

また、Mirandaには、Haskellにはない機能として、「対角化リスト内包表記」があり、`//` 記号を用いて、2つの無限リストからそれらを組み合わせたリストを生成できます。例えば、`[(x, y) // x <- [1..]; y <- [1..]]` は、`[(1, 1), (1, 2), (2, 1), (1, 3), (2, 2), (3, 1), ..]` のようなリストを生成します。

関数への引数の適用は、`sin x` のように関数に続けて引数を記述します。

Mirandaでは、他の純粋関数型言語と同様に、関数を引数として他の関数に渡したり、関数の結果として関数を返したり、データ構造の要素として関数を含めたりできます。また、すべての関数は1引数にカリー化されていると見なすことができ、引数の数が不足している場合は部分適用となります。


add a b = a + b
increment = add 1


この場合、`increment` は引数に1を加算する関数です。実際、`add 4 7` は2つの引数を取る関数ですが、これは単一引数 `7` に `4` を加算する関数とも解釈できます。

2つの引数をとる関数を中置演算子として使用できます。例えば、`add` 関数は `$add` として、`+` 演算子のように使用できます。逆に、2つの引数に作用する中置演算子を関数に変換することもできます。


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


これにより、引数に1を足す関数や、引数を2で割る関数、1を引数で割る関数を簡潔に記述できます。

Mirandaは強い型付け言語ですが、型宣言は必須ではありません。関数の型が明示されていない場合、インタープリタは引数の型や使われ方から型推論を行います。例えば、リストの逆転関数では、基本データ型に加えて、引数の型を問わない `anything` 型を使用できます。


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


これは任意のデータ型のリストに適用可能です。明示的に型を宣言する場合は次のようになります。


rev :: [] -> []


モジュール機構により、名前空間の分離も可能です。モジュール外から内部の名前が見えないようにすることで、名前の衝突を避けることができます。

コード例



以下のMirandaのスクリプトは、数の集合について、すべての部分集合を求める関数です。


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


以下の例は、「文芸的プログラミング」スタイルで記述されており、すべての素数のリストを提供する関数 `primes` を定義しています。


|| The infinite list of all prime numbers, by the sieve of Eratosthenes.

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]

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。