Haskell(/ ˈ h æ s k əl / [ 25 ])は、汎用、静的型付け、純粋関数型プログラミング言語であり、型推論と遅延評価を備えています。[ 26 ] [ 27 ] Haskellは、型安全な演算子オーバーロードのための型クラスやモナド入出力(IO)など、いくつかのプログラミング言語機能を開拓しました。論理学者Haskell Curryにちなんで名付けられました。[ 1 ] Haskellの主な実装はGlasgow Haskell Compiler(GHC)です。
Haskellのセマンティクスは歴史的にはMirandaプログラミング言語のセマンティクスに基づいており、これは初期のHaskellワーキンググループの取り組みの焦点となりました。[ 28 ]この言語の最後の正式な仕様は2010年7月に作成されましたが、GHCの開発は言語拡張を通じてHaskellを拡張し続けています。
Haskellは学界と産業界で使用されています。[ 29 ] [ 30 ] [ 31 ] 2021年5月現在、HaskellはGoogleのチュートリアル検索で28番目に人気のあるプログラミング言語であり、[ 32 ] GitHubソースコードリポジトリ のアクティブユーザーの1%未満を占めています。[ 33 ]
1985年にリサーチ・ソフトウェア社がミランダをリリースした後、遅延関数型言語への関心が高まりました。1987年までに、非厳密な純粋関数型プログラミング言語が12種類以上存在しました。ミランダは最も広く使われていましたが、プロプライエタリソフトウェアでした。オレゴン州ポートランドで開催された関数型プログラミング言語とコンピュータアーキテクチャに関する会議(FPCA '87)では、そのような言語のオープンスタンダードを定義する委員会を設立すべきだという強いコンセンサスが得られました。委員会の目的は、既存の関数型言語を共通の言語に統合し、将来の関数型言語設計の研究の基盤とすることだったのです。[ 34 ]
Haskell は、可能な限り既成のソリューションを統合しようとする委員会によって開発されました。
型クラスは、当時の言語における等価型と算術オーバーロードのアドホックな処理に対処するために、フィリップ・ワドラーとスティーブン・ブロットによって最初に提案されました。 [ 35 ]
Haskellの初期バージョン(バージョン1.2まで)では、ユーザーインタラクションと入出力(IO)はストリームベースと継続ベースの両方のメカニズムによって処理されていましたが、これらは一般的に不十分だと考えられていました。[ 36 ]バージョン1.3では、モナドIOが導入され、型クラスの高次種(型コンストラクタ)への一般化も導入されました。型クラスの構文糖を提供する「do記法」と併せて、MonadHaskellは参照透過性を維持しながら便利なエフェクトシステムを実現しました。
初期バージョンでのもう 1 つの注目すべき変更は、リファクタリングをより実用的にするために、「順次評価」操作seq(値間のデータ依存関係を作成し、遅延言語で過剰なメモリ消費を回避するために使用されます) を型クラスから標準関数に移動したことです。
Haskellの最初のバージョン(「Haskell 1.0」)は1990年に定義されました。[ 1 ]委員会の努力により、一連の言語定義(1.0、1.1、1.2、1.3、1.4)が生まれました。

FoldableTraversableApplicativeFunctorMonad1997年後半、この一連の作業はHaskell 98で最高潮に達しました。これは、安定した、最小限の、移植性の高い言語バージョンと、教育用および将来の拡張の基盤となる標準ライブラリを規定することを目的としていました。委員会は、実験的な機能の追加や組み込みによるHaskell 98の拡張や派生の作成を明示的に歓迎しました。[ 34 ]
1999年2月、Haskell 98言語標準は、Haskell 98レポートとして最初に出版されました。[ 34 ] 2003年1月には、改訂版がHaskell 98言語とライブラリ:改訂レポートとして出版されました。[ 27 ]この言語は急速に進化し続けており、現在のデファクトスタンダードとなっているのはグラスゴーHaskellコンパイラ(GHC)の実装です。[ 37 ]
2006年初頭、Haskell 98標準の後継となる、非公式にHaskell Primeと呼ばれる標準仕様を定義するプロセスが開始されました。[ 38 ]これは、言語定義を継続的に改訂していく段階的なプロセスとして意図されており、最大1年に1回の改訂版を作成することになっていました。最初の改訂版はHaskell 2010と名付けられ、2009年11月に発表され[ 2 ]、2010年7月に公開されました。
Haskell 2010 では、以前はコンパイラ固有のフラグによって有効化されていた、よく使用され議論の余地のない機能がいくつか追加されました。
Data.ListではなくList)。この拡張機能はHaskell 98の補遺で規定され、実際には広く使用されていました。fact (n+1) = (n+1) * fact n)は許可されなくなりました。この構文糖は、 演算子を使用しているように見えるコードでありながら(+)、実際には と を使用するようにデシュガー処理されており、(-)誤解を招く意味を持っていました(>=)。LANGUAGEが規定されました。2010年までに、言語には数十の拡張機能が広く使用されるようになり、GHC(および他のコンパイラ)は、LANGUAGE識別子のリストを使用して個々の拡張機能を指定するためのプラグマを提供しました。Haskell 2010コンパイラは、このHaskell2010拡張機能のサポートが必須であり、Haskell 2010で追加された拡張機能に対応する他のいくつかの拡張機能のサポートが推奨されています。次の正式仕様は2020年に予定されていました。[ 3 ] 2021年10月29日、GHCバージョン9.2.1でGHC2021拡張がリリースされました。これは正式な言語仕様ではありませんが、安定しており広く使用されているGHC拡張をHaskell 2010に統合したものです。[ 39 ] [ 40 ]
Haskellは、遅延評価、ラムダ式、パターンマッチング、リスト内包表記、型クラス、型多態性といった機能を備えています。Haskellは純粋関数型プログラミング言語であり、関数は一般的に副作用を持ちません。副作用を表すために、関数の型とは直交する独自の構造が存在します。純粋関数は、その後実行される副作用を返すことができ、これは他の言語の非純粋関数をモデル化しています。
Haskellは、 Hindley-Milner型推論に基づく強力で静的な型システムを備えています。この分野における主要な革新は型クラスであり、これは当初、言語にオーバーロードを追加するための原理的な方法として考案されましたが[ 41 ]、その後、より多くの用途が見出されています[ 42 ] 。
副作用を表す構造は、モナドの一例です。モナドとは、エラー処理、非決定性、構文解析、ソフトウェアトランザクショナルメモリといった様々な計算をモデル化できる汎用的な枠組みです。これらは通常のデータ型として定義されていますが、Haskellはそれらを利用するための糖衣構文を提供しています。
Haskellはオープンに公開された仕様を持ち[ 27 ]、複数の実装が存在します。その主要な実装であるGlasgow Haskellコンパイラ(GHC)は、ほとんどのプラットフォームで動作するインタープリタとネイティブコードコンパイラの両方です。GHCは、一般化代数データ型や型ファミリといった最近の革新を取り入れた豊富な型システムで知られています。コンピュータ言語ベンチマークゲームでは、並行性と並列性の高性能な実装も高く評価されています[ 43 ]。
この言語には活発で成長を続けるコミュニティが存在し、オンラインパッケージリポジトリHackageでは5,400以上のサードパーティ製のオープンソースライブラリとツールが利用可能です。[ 44 ]
Haskell の「Hello, World!」プログラム(最後の行のみが厳密に必要です):
module Main ( main ) where -- はインタープリタでは必要ありませんが、モジュールファイルではデフォルトですmain :: IO () -- コンパイラはこの型定義を推論できますmain = putStrLn "Hello, World!"Haskell の階乗関数は、いくつかの異なる方法で定義されています (最初の行は型注釈で、オプションであり、各実装で同じです)。
階乗:: (積分a ) => a -> a-- 再帰の使用(「ifthenelse」式を使用)factorial n = if n < 2 then 1 else n * factorial ( n - 1 )-- 再帰を使用(パターンマッチング付き)factorial 0 = 1 factorial n = n * factorial ( n - 1 )-- 再帰を使用(ガード付き)factorial n | n < 2 = 1 | otherwise = n * factorial ( n - 1 )-- リストと「product」関数を使用するfactorial n = product [ 1 .. n ]-- fold を使用する(「積」を実装)factorial n = foldl ( * ) 1 [ 1 .. n ]-- ポイントフリースタイルの階乗= foldr ( * ) 1 . enumFromTo 1Haskell の固定小数点コンビネータを使用すると、明示的な再帰なしでこの関数を記述できます。
Data.Functionをインポートする(修正)階乗= facを固定します。ただし、 fac f x | x < 2 = 1 |それ以外の場合は= x * f ( x - 1 )Integer型は任意精度を持つため、このコードはfactorial 100000精度を失うことなく (456,574 桁の数値) などの値を計算します。
リスト上のクイックソートに似たアルゴリズムの実装。最初の要素がピボットとして取得されます。
-- 型注釈(オプション、各実装で同じ)quickSort :: Ord a => [ a ] -> [ a ]-- リストの内包表記を使用するquickSort [] = [] -- 空のリストはすでにソートされているquickSort ( x : xs ) = quickSort [ a | a <- xs , a < x ] -- リストの左側をソートする++ [ x ] ++ -- ソートされた2つの部分の間にピボットを挿入するquickSort [ a | a <- xs , a >= x ] -- リストの右側をソートする-- フィルターを使用するquickSort [] = [] quickSort ( x : xs ) = quickSort ( filter ( < x ) xs ) ++ [ x ] ++ quickSort ( filter ( >= x ) xs )リストされている実装はすべてオープンソースライセンスの下で配布されています。[ 45 ]
Haskell 98 標準に完全またはほぼ準拠している実装には次のものがあります。
アクティブにメンテナンスされなくなった実装には次のものが含まれます。
完全に Haskell 98 に準拠しておらず、バリアント Haskell 言語を使用する実装には次のものがあります。
Haskell用に書かれた注目すべきウェブフレームワークには以下のものがある: [ 67 ]
Jan-Willem Maessenは2002年に、Simon Peyton Jonesは2003年に、遅延評価に関連する問題について議論しましたが、その理論的動機も認めていました。[ 68 ] [ 69 ]パフォーマンスの向上などの純粋に実用的な考慮事項に加えて、[ 70 ]彼らは、遅延評価によってプログラマがコードのパフォーマンス(特にメモリの使用)を判断することがより困難になると指摘しています。
2003年、Bastiaan Heeren、Daan Leijen、Arjan van IJzendoornもHaskell学習者にとっての障害について言及している。「Haskellの繊細な構文と洗練された型システムは諸刃の剣です。経験豊富なプログラマーには高く評価される一方で、Haskellの汎用性がしばしば不可解なエラーメッセージにつながるため、初心者にとってはフラストレーションの原因にもなります。」[ 71 ]ユトレヒト大学の研究者たちは、エラーメッセージに対処するために、Heliumと呼ばれる高度なインタープリタを開発しました。これは、Haskellの一部の機能の汎用性を制限することで、エラーメッセージの使いやすさを向上させました。特に、型クラスをデフォルトで無効にしています。[ 72 ]
ベン・リップマイヤーは、遅延評価の推論や可変配列などの従来のデータ構造の使用に関するHaskellの難しさに対処するために、型と効果のシステムを備えたデフォルトで厳密な(明示的な注釈によって遅延評価する)Haskellの方言としてDisciple [ 73 ]を設計しました。[ 74 ]彼は( 20ページ)「破壊的更新はプログラマに2つの重要かつ強力なツールを提供します...オブジェクトのコレクションを管理するための効率的な配列のようなデータ構造のセットと...プログラマの負担を最小限に抑えながらプログラムのすべての部分に新しい値をブロードキャストする機能です。」と主張しています。
Standard MLの著者の一人であるロバート・ハーパーは、入門プログラミング教育にHaskellを用いない理由を述べている。その例としては、非正格評価によるリソース利用の推論の難しさ、遅延評価がデータ型の定義と帰納的推論を複雑にすること、そしてHaskellの(古い)クラスシステムがMLのモジュールシステムに比べて「劣っている」ことが挙げられる。[ 76 ]
HaskellのビルドツールであるCabalは、歴史的に、同じライブラリの複数のバージョンの処理が不十分であるとして批判されてきました。これは「Cabal hell」と呼ばれる問題です。StackageサーバーとStackビルドツールは、これらの批判に応えて開発されました。[ 77 ] Cabalはその後、パッケージマネージャーであるNixのアイデアを借用することでこの問題に対処し、[ 78 ] 2019年には新しいアプローチがデフォルトになりました。
CleanはHaskellに近い、やや古いタイプの言語です。Haskellとの最大の違いは、入出力(I/O)と副作用 にモナドではなく一意性型を使用している点です。
Haskell にヒントを得た、異なる型システムを持つ一連の言語が開発されています。以下にその一部を示します。
その他の関連言語は次のとおりです:
注目すべき Haskell バリアントには次のようなものがあります。
Haskellのイベントは、国際関数型プログラミング会議(ICFP)と同時に定期的に開催されており、Haskellシンポジウム(旧Haskellワークショップ)や関数型プログラミングの商用ユーザーなどのワークショップが含まれています。[ 79 ]その他のイベントには、Haskell実装者ワークショップ、[ 80 ] 、チューリッヒのZuriHac 、[ 81 ]、Hac:Haskellハッカソンなどがあります。[ 82 ]
{{cite news}}: CS1 メンテナンス: 場所 (リンク)シーケンス式
と
ワークフロー
と呼ばれる2つの高度な言語機能に関して Haskell から影響を受けています
。
言語は、言語専門家、ドキュメンテーションの達人、コンパイラ最適化の達人、そしてアイデアの洗練と実戦テストに役立つフィードバックを提供してくれた非常に重要な社内ドッグフーディンググループのたゆまぬ努力の成果です。もちろん、この分野の多くの言語が苦労して得た経験からも大きな恩恵を受けており、Objective-C、Rust、Haskell、Ruby、Python、C#、CLUなど、数え切れないほど多くの言語からアイデアを得ています。