(ハスケル)は非正格な評価を特徴とする純粋関数型プログラミング言語である。名称は数学者であり論理学者であるハスケル・カリーに由来する。 は高階関数や静的多相型付け、定義可能な演算子、例外処理といった多くの言語で採用されている現代的な機能に加え、パターンマッチングやカリー化、リスト内包表記、ガードといった多くの特徴的な機能を持っている。また、遅延評価や再帰的な関数や代数的データ型もサポートしているほか、独自の概念として圏論のアイデアを利用し参照透過性を壊すことなく副作用のある操作(例えば 代入、入出力、配列など)を実現するモナドを含む。このような機能の組み合わせにより、手続き型プログラミング言語では記述が複雑になるような処理がしばしば簡潔になるばかりではなく、必要に応じて手続き型プログラミングを利用できる。GUI開発向けサポートの新しい方法を提供する、 と呼ばれる に似た言語もある。 と の最大の違いは、モナドを代用する一意型の採用である。1985年、遅延関数言語である がリサーチ・ソフトウェア社によって発表された。1987年にはこのような非正格な純粋関数型プログラミング言語が十二以上存在していたが、そのうち最も広く使われていた はパブリックドメインではなかった。オレゴン州ポートランドで開催された () において開かれた会議中に、遅延関数型言語のオープンな標準を作成するための委員会が発足されるべき、という強い合意が参加者のあいだで形成された。委員会の目的は、関数型言語のデザインにおける将来の研究のための基礎として役立つ共通のものへと、既存の関数型言語を統合することであった。最初の版の ( 1.0)は1990年に作成された。委員会の活動は一連の言語仕様を結果に残し、1997年後半にそのシリーズは、安定しており小さく可搬なバージョンの言語仕様と、学習用および将来の拡張の基礎としての基本ライブラリなどを定義した 98 に到達した。実験的な機能の付加や統合を通じて 98 の拡張や派生物を作成することを、委員会ははっきりと歓迎した。1999年2月、 98 言語標準は最初に として発表された。2003年1月、改定されたバージョンが として発表された。GHC に代表されるように、 は急速に発達しつづけている。2006年前半、非公式に ()と呼ばれている 98 の後継の作成プロセスが開始された。このプロセスは 98 のマイナーバージョンアップを目的としている。 2010 は他のプログラミング言語とのバインディングを可能にする (FFI)を に追加し, いくつかの構文上の問題を修正する(正式な構文を変更する)。「codice_1 パターン」と呼ばれる構文を削除し, codice_2というような形式の定義はもはや許されない。 に 2010 のソースかどうかや, いくつかの必要な拡張の指定を可能にする言語プラグマ構文拡張を導入する。 2010 に導入された拡張の名前は, codice_3, codice_4(階層化ライブラリ), codice_5, codice_6, codice_7, codice_8, codice_9, codice_10, codice_11, codice_12 である。ここでは以降の解説を読む上で必要な の文法規則を簡単に説明する。 の構文は数学で用いられるものによく似せられていることに注意されたい。 の型名は先頭が大文字でなければならない。標準で存在する単純なデータ型としては、codice_13(真偽値)型、codice_14(整数)型、codice_15(単精度浮動小数点数)型、codice_16(文字)型、codice_17(文字列)型などが予め定義されている。任意の式の型を定義するには、式と型の間に codice_18 記号をおく。また、変数などのシンボルを定義する際に変数名を式に指定して書くことで、その変数の型を指定することができる。例えば、次は円周率およびネイピア数を定数として定義し、さらにその型も浮動小数点型として指定している。関数の型は、各引数の間を codice_19 記号で区切って表記する。関数は引数をひとつ適用するたびに、その型は codice_19 で区切られたうちの一番左が消えた型となると考えればよい。例えば、ふたつの整数を引数にとりその最大公約数を返す関数 codice_21 の型は次のように定義される。型変数を使い、型を抽象化することもできる。これは のテンプレートや のジェネリクスに相当するが、様々な種(型の型)に適用できるためより柔軟である。例えば、codice_22 型の値をとり、それをそのまま返す恒等関数 codice_23 を型の指定とともに定義すると以下のようになる。ここで任意の型を示す型名 codice_22 が定義に使われているが、このように先頭が小文字で始まっている型名は具体的な型名ではなく型変数である。この関数はあらゆる型の値を引数にとることができる。また、データ型はパラメータとして型変数を持つことができる。例えば、スタックやハッシュテーブルなどのデータ型は、その要素の型を型変数として定義する。ハッシュテーブルを実装するデータ型 codice_25 があり、キーに文字列(codice_17)、値に整数(codice_14)を持つハッシュテーブル codice_28 の型は次のようになる。そのほか、特殊な表記を持つ型としてリストとタプルがある。リストは で極めて頻繁に用いられるため、特別な構文が用意されている。リストは要素の型を角括弧で囲む。次は codice_16(文字)のリストを束縛する変数 codice_30 の定義である。タプルは要素の型をカンマで区切り、括弧で囲む。次は codice_15(浮動小数点数)の値をもつ2次元座標のタプルが束縛される変数 codice_32 の定義である。タプルは2以上ならいくつでも要素を持つことができる。1要素のタプルは優先順位の括弧と表記が衝突し、また用途がないので存在しない。要素数がゼロのタプルは特に「ユニット」(codice_33) と呼ばれ、有効な値を持たないなどの時に使われる。codice_34 キーワードを用いて、型に別名をつけることができる。次は codice_35 に codice_17 という別名をつけている。関数名は先頭が小文字でなければならず、記号を含むことはできない。演算子名は記号のみで構成されていなければならない。関数の定義ではC言語のような引数を囲む括弧や区切りのカンマは使われず、単に引数を空白文字で区切って表記する。次は先程示した恒等関数 codice_23 に、型の定義に加えて本体の定義もした例である。関数の適用も同様で、単に関数に続いて空白文字で区切った引数を並べればよい。以下では上記の恒等関数 codice_23 を(ここでは使う必要はないが)適用して、別の変数を定義した例である。引数がつねに2個であることや引数の間に演算子をおくことなどを除けば、演算子についても関数の定義や適用と同様である。標準で定義されている算術演算子を使って、BMIを計算する関数 codice_39 を定義してみる。この定義では codice_15 を引数にとり codice_15 で結果を返すが、この関数では codice_42 を引数に使うことはできない。どの浮動小数点数型でも扱えるような関数にするには、次のように型変数を使えばよい。このバージョンの関数 codice_39 では引数や返り値の型が codice_22 とされているが、これにさらに codice_22 は codice_46 であるとの制約をつけている。codice_46 は codice_15 や codice_42 を抽象化する型クラスであり codice_50 や codice_51 といった演算子を適用できるので、codice_39 の定義においてこれらの演算子を使うことができている。また、整数などの値は引数に取れないし、返り値は引数に与えた型で戻ってくる。関数と演算子は新たに定義し直さなくても相互に変換可能である。関数を演算子として使うには、関数を codice_53 (バッククォート)で囲む。逆に、演算子を関数として使うには括弧で囲む。例えば、整数を除算する関数 codice_54 はよく演算子として使われる。なお、関数適用の優先順位はすべての演算子の優先順位よりも高い。ここではあまり他の言語では見られない 特有の機能を中心に解説する。ここでは説明していないが、現代的な実用言語では常識となっているガーベジコレクション、例外処理、モジュール、外部関数の呼び出し、正規表現ライブラリなどの機能は、 にも当然存在している。 は遅延評価を基本的な評価戦略とする。ほとんどの言語では関数の呼び出しにおいて引数に与えられたすべての式を評価してから呼び出された関数に渡す先行評価を評価戦略とするが、これに対し ではあらゆる式はそれが必要になるまで評価されない。次の定数 codice_55 は評価すると常に codice_56 を返すが、その定義には未定義の式を含む。ここで、codice_57 は常に第1引数を返す定数関数である。また、codice_58 は整数の除算を行う演算子であり、codice_59 は codice_60 に相当し、この値は未定義であり、この部分を評価すればエラーになる。正格評価をする言語でこのような式を評価しようとすると、ゼロ除算によるエラーになるであろう。しかし 上記の定数 codice_55 を評価してもエラーにはならない。codice_57 は第1引数をつねに返すので第2引数を評価する必要はなく、第2引数に与えられた式 codice_59 は無視されるので評価されないからである。遅延評価がデフォルトで行われることにより、不要な計算は省かれ、参照透過性により同じ式を複数回評価する必要もなくなるため、 では最適化によって計算効率の向上が期待できる場合がある。ただし、頻繁に新たな値を計算する場合は正格評価のほうが効率がよく、必要に応じてcodice_64関数やBangPatterns拡張による明示により正格評価もできる。 では関数のデータ型を明示しなくても処理系が自動的に型を推論する。以下は型の宣言を省略し、本体のみを宣言した引数の平方を返す関数 codice_65 である。この場合 codice_65 の型は型推論され、次のように明示的に型を宣言したのと同じになる。この宣言は、「codice_67のインスタンスである codice_22 の型の値を引数にとり、codice_22 の型の値を返す」と読める。ここでは「codice_70」演算子が適用可能な最も広い型である codice_71 が選択されており、整数や浮動小数点数、有理数のような codice_67 のインスタンスであるあらゆる型の値を渡すことができる。外部に公開するような関数を定義するときは、型推論によって自動的に選択される最も広い型では適用可能な範囲が広すぎる場合もある。codice_73 のみを渡せるように制限する場合は、次のように明示的に型を宣言すればよい。型推論のため、 は型安全でありながらほとんどの部分で型宣言を省略できる。なお、次のコードは型宣言が必要な例である。codice_74 は文字列をその文字列があらわすデータ型に変換する抽象化された関数である。このコードはコンパイルエラーになる。codice_74 は複数のインスタンスで実装されており、数値なら数値型に変換する codice_74、リストならリストに変換する codice_74 というように型ごとに実装が存在する。 の型は総て静的に決定されなければならない。このコード場合、プログラマは という型をもつ実装の codice_74 が選択されると期待しているであろうが、これはコンパイラによる静的な型検査では決定できない。つまり、 コンパイラは codice_74 の返り値を受け取っている関数 codice_80 の型を検査し多数の実装の中から適切な codice_74 を選択しようとするが、codice_80 は codice_83 のインスタンスが存在するあらゆる型を引数にとるため、型推論によっても codice_74 の型を一意に決定できない。これを解消するひとつの方法は、codice_18 によって型を明示することである。また、そもそも codice_74 の返り値を整数型しか取らない関数に与えていればあいまいさは生じず、型推論は成功する。他の言語、たとえば でこのような抽象的な関数を書こうとしても、 では返り値の値の型によって関数を選択するようなことはできない(引数の型によって選択するメソッドのオーバーロードは存在する)。そのため、関数の実装ごとに別の名前をつけてプログラマに明示的に選択させて解決させることになる。この方法は簡潔でわかりやすいが、抽象性の高さに基づく再利用性という点では のような多相には劣ってしまう。 のデータ型には代数的データ型と呼ばれる、C言語などでいう構造体や列挙体の性質を兼ね備えたものが用いられる。次の例は二つのInt型の値をフィールドに持つ二次元の座標、codice_87 型を定義したもので、これは代数的データ型の構造体的な性質を示す。先頭のトークン「codice_88」は代数的データ型の宣言であることを示す予約語である。ここで最初の codice_87 はデータ型名を表し、次の codice_87 はデータコンストラクタ名を示す。データコンストラクタは値を定義するための特殊な関数といえる。データコンストラクタは後述するパターンマッチによって値を取り出す際にも用いられる。次の例はトランプの4つのスーツを示す codice_91 型を定義したものである。codice_92、codice_93、codice_94、codice_95 の4つのデータコンストラクタが定義されており、codice_91 型の式は codice_92、codice_93、codice_94、codice_95 のいずれかの値をとる。次の例は codice_17 型の値を格納する二分木の型である。codice_102(葉)は codice_17 型の値を持ち、codice_104(枝)は codice_102 もしくは codice_104 である codice_107 型の変数を二つ持つ。これは代数的データ型の構造体的な性質と列挙体的な性質の両方が現れている。GADTと呼ばれる機能を使うと、コンストラクタの型を明示してデータ型を定義することもできる。 は第一級関数をサポートしており、高階関数を定義することができる。つまり、関数の引数として関数を与えたり、返り値として関数を返すことができる。無名関数は codice_108 (バックスラッシュ)から始まり、それに続いて引数となる変数、引数と本体のあいだに codice_19 記号をおく。codice_110 モジュールに定義されているリストのソートを行う関数 codice_111 は、二つの要素に大小関係を与える関数を引数にとるが、無名関数を使うと例えばリストをその長さの短い順にソートする関数 codice_112 は次のように定義できる。 において、2つの引数を持つ関数は、1つの引数をとり「1つの引数をとる関数」を返す関数と同義である。このように、関数を返すことで全ての関数を1つの引数の関数として表現することをカリー化という。(あえてタプルを使うことで複数の引数を渡すような見かけにすることもできるが。)次の例は2つの引数をとり、そのうち値が大きい値を返す関数 codice_113 である。この関数maxは無名関数を用いて次のように書き換えることができる。先ほどの表現とまったく同様に動作するが、この表現では関数を返す様子がより明らかになっている。さらに、次のようにも書き換えることができる。あるいは、codice_114は、codice_115の糖衣構文であるとも言える。このため、 の定義は変数に束縛するのが定数であるか関数であるかにかかわらず、「変数 = 値」という一貫した形でも定義できる。カリー化によって、 のあらゆる関数は引数を部分適用することができる。つまり、関数の引数の一部だけを渡すことで、一部の変数だけが適用された別の関数を作り出すことができる。また、 では演算子を部分適用することすら可能であり、演算子の部分適用をとくにセクションと呼ぶ。任意のリストをとり、その要素から条件にあう要素のみを取り出す関数 codice_116 が標準ライブラリに定義されている。この関数では第一引数に残す要素を判定する関数をとるが、このときに部分適用を使えばそのような関数を簡潔に書くことができる。整数のリストから正の値のみを取り出す関数 codice_117 は次のように定義できる。ここで、codice_117 および codice_116 の第2引数はソースコード上に現れずに記述できているが、このように単純に書けるのもカリー化の恩恵によるものである。 では関数の引数を様々な形で受け取ることができる。次は整数の要素をもつリストの全要素の合計を返す関数 codice_120 である。codice_120 の関数本体の定義がふたつあるが、このうち引数の実行時の値と適合する本体が選択され呼び出される。上の本体定義では、引数が空のリストであるときのみ適合し、呼び出される。下の本体定義では、引数が少なくともひとつの要素を持つとき適合し、codice_122 に先頭の要素が束縛され、codice_123 に残りのリストが束縛される。この例の場合はパターンに漏れはないが、もし適合するパターンが見つからない場合はエラーになる。複数の返り値を扱うのもタプルなどを利用して極めて簡明に書くことができる。このとき、定義される変数は codice_122 および codice_125 で、それぞれ codice_122 は codice_127 に、codice_125 は codice_129 に定義される。 で順序付けられた複数の値を扱うのにもっとも柔軟で簡潔な方法はリストを用いることである。次は四季の名前のリストである。次は初項10、公差4の等差数列のリストである。このリストは無限リストであり、その長さは無限大である。次の式は先ほどの数列の先頭20項を要素に持つリストである。codice_130 はリスト codice_131 の先頭 codice_132 個の項を要素に持つリストを返す関数である。もし正格な動作を持つ言語でこのような定義をしようとすると関数 codice_133 に値を渡す前に無限リストを生成することになるが、長さが無限のため無限リストの生成が終わることはなく関数 codice_133 がいつまでも呼び出されなくなってしまう。 は遅延評価されるため、このようなリストを定義しても必要になるまで必要な項の値の生成は遅延される。このように無限リストを扱えるのは の大きな強みである。次は素数列をリスト内包表記を用いて定義した一例である。リストはその柔軟性から再帰的な関数での値の受け渡しに向いているが、任意の位置の要素にアクセスするためには参照を先頭からたどる必要があるのでランダムアクセスが遅い、要素を変更するたびにリストの一部を作り直さなければならないなどの欠点がある。このため にも配列が用意されており、高速な参照や更新が必要なプログラムではリストの代わりに配列を用いることでパフォーマンスを改善できる可能性がある。型クラスは相異なるデータ型に共通したインターフェイスを持つ関数を定義する。例えば、順序づけることができる要素をもつリストをソートできる関数 codice_135 を定義することを考える。リストの要素のデータ型は関数 codice_135 を定義するときには不明であり、その要素をどのように順序付けるかを予め決定しておくことはできない。数値型も文字列型もそれぞれのデータを順序付けることができるであろうが、共通してデータの順序を返す抽象的な関数 codice_137 を定義することができれば、それを用いてソートすることができる。まず型クラス codice_138 を定義して、順序付ける関数 codice_137 の形式を定義する。値の順序を調べる関数 codice_140 は codice_122 → codice_125 が昇順のときは負の値、降順の時は正の値、codice_122 と codice_125 が等しいときは codice_145 を返すものとする。ここで codice_146 は型クラスの宣言であることを示す予約語である。型クラスを実装するには、対象のデータ型に対してインスタンス宣言を行う。次は型 codice_22 の型クラス codice_138 に対するインスタンスを宣言したものである。このインスタンス宣言により、codice_149 のインスタンスである任意の型のリストを辞書順に比較できる。例えば、文字列 codice_16 は codice_149 のインスタンスの codice_16 のリストであり、このインスタンス定義により codice_137 を適用することができるようになる。ここで関数 codice_154 は文字 codice_155 を数値に変換する関数である。codice_138 のインスタンスを定義する型 codice_22 を codice_158 および codice_149 のインスタンスを持つものに限定しているので(codice_160 の部分)、インスタンス定義の内部で codice_158 の関数である codice_162 や codice_149 の関数である codice_164 を使うことができている。次にリストをクイックソートする関数 codice_135 を示す。型クラスを用いて順序付ける関数 codice_137 を抽象化したため、このように型クラス codice_138 のインスタンスを持つ全ての型の値に適用できる一般化されたソート関数を定義できるのである。この関数 codice_135 は次のように使う。すべての式が参照透過である においては、副作用を式の評価そのものでは表現できない。そのため、 では圏論のアイデアを利用したモナドによって入出力が表現されており、 でも最も特徴的な部分となっている。次は による の一例である。実際に単独で実行可能形式にコンパイルできる、小さいが完全なプログラムの一例にもなっている。codice_175 と codice_172 はそれぞれ次のような型を持っている。純粋関数型である では codice_175 もやはり副作用はなく、codice_175 は一行読み込むという動作を表す値を常に返す。このように入出力の動作を表す値をアクションと呼ぶ。codice_175 が返すのは codice_17 そのものではなくあくまで codice_182 という型を持ったアクションであって、それを codice_172 の引数に与えることはできない。正しいエコープログラムの一例は次のようになる。ここでは演算子 codice_184 によってふたつのアクションを連結している。このとき、codice_169 は一行読み込みそれを出力するというアクションとなり、このプログラムを実行すると処理系は codice_169 が持つアクションの内容を実行する。このアクションを実行すると、codice_175 は一行読み込み、それを codice_172 に渡す。このとき、読み込まれたデータにこれらのアクションの外側からアクセスすることはできない。このため、この式は参照透過性を保つことができる。モナドは、Freeモナド、Operationalモナドと呼ばれる構造により、より単純なデータ型から導出することもできる。これにより、非常に強力な依存性の注入が実現できる。以下の単純な例は関数型言語としての構文の実例にしばしば用いられるもので、 で示された階乗関数である。階乗を単一の条件による終端を伴う再帰的関数として表現している。これは数学の教科書でみられる階乗の表現に似ている。 コードの大半は、その簡潔さと構文において基本的な数学的記法と似通っている。この階乗関数の1行目は関数の型を示すもので、省略可能である。これは「関数 codice_189 は codice_73 から codice_73 へ(codice_192)の型を持つ(codice_18)」と読める。これは整数を引数としてとり、別の整数を返す。もしプログラマが型注釈を与えない場合、この定義の型は自動的に推測される。2行目では の重要な機能であるパターンマッチングに頼っている。関数の引数が codice_145であれば、これは codice_195 を返す。その他の場合は3行目が試される。これは再帰的な呼び出しで、nが0に達するまで繰り返し関数が実行される。ガードは階乗が定義されない負の値から3行目を保護している。このガードが無ければこの関数は0の終端条件に達することなく、再帰してすべての負の値を経由してしまう。実際、このパターンマッチングは完全ではない。もし関数facに負の整数が引数として渡されると、このプログラムは実行時エラーとともに落ちるであろう。codice_196のように定義を追加すれば適切なエラーメッセージを出力することができる。引数 codice_197 を伴う高階関数で表現された単純な逆ポーランド記法評価器が、パターンマッチングと型クラス codice_198 を用いた codice_199 節で定義されている。空リストを初期状態とし、codice_197 を使って一語ずつ文字列を解釈していく。codice_197 は、注目している語が演算子ならばその演算を実行し、それ以外ならば浮動小数点として計算スタックに積んでいる。次はフィボナッチ数列のリストである。ある値nに対するfib(n)は一回しか計算しないようになっており、その点ではナイーブなフィボナッチと異なる効率の良いコードとなっている。無限リストは 余再帰(リストの後ろの値は要求があったときに codice_145 と codice_195 の二つの初期要素から開始され算出される)によって実現される。このような定義は遅延評価の実例で、 プログラミングでも重要な部分である。ただし、フィボナッチ数列の生成の場合は、ある要素の値が必要であれば、その要素より前にある要素の値は全て必要である。従って、遅延させた上で結局は後から全てその値を求めることになり、むしろ無駄であるので、この場合は遅延させない組込関数seqを使用したほうが効率は良くなり、fib 1000000 といったような値を計算するような場合には差が見えてくる。あるいはリストの先に出る値から順番に計算させるとそのほうが速い、といったことが起きる。(さらに、フィボナッチ数はnに対して2と大きな値になるので、そのようなBigIntegerの加算のコストも掛かり、以前にこの場所に書かれていたような「線形時間でのフィボナッチ数列の生成」は、大きい値では不可能である)どのように評価が進行するかの例示のために、次は6つの要素の計算の後の codice_204 と codice_205 の値と、どのようにcodice_206 が4つの要素を生成し、次の値を生成し続けるかを図示したものである。次はGHCで使える言語拡張で、リスト内包表記を並列的な生成を記述できるよう拡張するParallelListCompを用いて書いた同様の式である。(GHCの拡張は特別なコマンドラインフラグ、またはLANGUAGEプラグマによって有効にしなければならない。詳しくはGHCのマニュアルを参照のこと)先に見た階乗の定義は、次のように関数の列を内包表記で生成して書く事もできる。特に簡潔に書ける例として、ハミング数が順番に並ぶリストを返す以下のような関数がある。上に示されたさまざまな codice_204 の定義のように、これはオンデマンドに数のリストを実現するために無限リストを使っており、codice_195 という先頭要素から後続の要素を生成している。ここでは、後続要素の構築関数は codice_199 節内の記号 codice_210 で表現された中置演算子で定義されている。各|は、等号の前半の条件部分と、後半の定義部分からなるガード節を構成する。parsec は で書かれたパーサコンビネータである。パーサの一種であるがコンパイラコンパイラとは異なり、codice_211 はパーサのソースコードを出力するのではなく、純粋に の関数としてパーサを構成する。 のようにプログラミング言語と異なる言語を新たに習得する必要がなく、高速でかつ堅牢で、型安全で、演算子の結合性や優先順位を考慮したパーサを自動的に構成したり、動的にパーサを変更することすらできる。派生として、大幅に高速なパースが可能なattoparsec、高機能でより洗練されたtrifectaがある。codice_212 はデータ駆動型のテストを行うモジュールである。自動的にテストデータを作成してプログラムの正当性をテストすることができる。lensはアクセサの概念を一般化するライブラリであり、様々なデータ構造に対して共通のインターフェイスを与える。Getter、Setterは一つの関数として表現されており、それらを合成することもできる。JSONやXMLの処理にも応用できる。 は他のプログラミング言語には見られない多くの先進的機能を持っているが、これらの機能のいくつかは言語を複雑にしすぎており、理解が困難であると批判されてきた。とりわけ、関数型プログラミング言語と主流でないプログラミング言語に対する批判は にもあてはまる。加えて、 の潔癖さとその理論中心の起源に起因する不満がある。2002年に Jan-Willem Maessen、2003年に Simon Peyton Jones が遅延評価に関連するこの問題を議論し、その上でこの理論的動機を認識した。彼らは実行時のオーバーヘッドの悪化に加え、遅延はコードのパフォーマンスの推察をより困難にすると言及した。2003年に Bastiaan Heeren と Daan Leijen、Arjan van IJzendoorn は の学習者にとってのつまづきに気がついた。これを解決するために、彼らは と呼ばれる新たなインタプリタを開発し、この中でいくつかの型クラスのサポートを取り除き、 の機能の一般化を制限することによってエラーメッセージのユーザ親和性を改善した。以下は 98 仕様を完全に満たす、または仕様に非常に近く、オープンソースライセンスの下で配布されているものである。ここには現在のところ商用のHaskell実装は含まれない。
出典:wikipedia
LINEスタンプ制作に興味がある場合は、
下記よりスタンプファクトリーのホームページをご覧ください。