The Early History of the F# Language

(これは The Early History of F# (HOPL IV -- first draft) の日本語訳です。翻訳許可をくださったDon Syme氏に感謝します。I would like to thank Dr. Don Syme for letting me translate this paper into Japanese.)

DON SYME, 主任研究員, Microsoft; F# 言語デザイナー; F# コミュニティ貢献者


本稿ではF# プログラミング言語の起源と初期の歴史について説明します。 1970年代、80年代、90年代の強く型付けされた関数型プログラミング(FP)の起源から始めます。 同時期に、Microsoftはソフトウェア業界を支配するために設立され、成長しました。 1997年に、Javaへの応答として、Microsoftは内部プロジェクトを開始しました。これは最終的に.NETプログラミングフレームワークおよびC# 言語になりました。 1997年から、ケンブリッジのMicrosoft Researchで学術関数型プログラミングと産業界が結合しました。 研究者たちは、Project 7、つまり.NETに複数の言語を取り入れるための最初の取り組みを介して同社と関わりを持ち、そして1998年に.NET Genericsを、2002年にF# を発表しました。 F# は、1990年代半ばの「オブジェクト指向の津波」に対する強く型付けされた関数型プログラミングの提唱者たちによるいくつかの回答のうちの1つでした。 F# のコア機能の開発は2004年から2007年にかけて行われました。Microsoftによる2007年から2010年にかけてF# の「製品化」とF# 2.0のリリースをもたらした意思決定プロセスについて説明します。 オブジェクトプログラミング、クォート、静的に解決された型パラメーター、アクティブパターン、コンピュテーション式、非同期、測定単位、型プロバイダーなど、F# の特徴的な機能の起源について説明します。 F# 3.0〜4.5を含む2010年以降のF# の主要な開発、および複数の配信チャネルを持つオープンソースのクロスプラットフォーム言語としてのその進化について説明します。 F# のいくつかの使用法と、F# がこれまでに他の言語に与えた影響を調べることによって結論を下します。


注:参考文献の中には、現在脚注形式のものがあります -- このドラフトについて早期のフィードバックをくれた人々からのコメントに応えて追加されたものです。 セカンドドラフトの投稿では、これらは引用に変換されます。

F# プログラミング言語の歴史は、1970年代から現在に至るまで続く物語です。 1970年代初頭、Robin Milnerと彼の同僚であるLockwood MorrisとMalcolm Neweyの頭の中に、 構造化情報の操作に適した簡潔で完全に型推論された関数型プログラミング言語のアイディアが生まれました(Gordon、2000)。 LISPの伝統に基づいて(そして実際にその実装手段としてLISPを使用して)、この言語はML -- Meta Language -- になり、 そしてそれが、Edinburgh ML、Miranda、Haskell、Standard ML、OCaml、Elm、ReasonML、およびPureScriptを含む 「強く型付けされた関数型プログラミング言語」の伝統の根底にあります。 F# はこのファミリーの一部です。

Standard MLの歴史は他の場所で語られています(MacQueen、2015)。 MLファミリー言語はしばしば形式主義に関連しています。これは本稿の後半で検討します。 しかし、Milnerと共同作業者の最大の関心事は、当初から実用的なユーザビリティでした。 このグループは特定の目的のために彼らの言語を必要としました: LCFと呼ばれる定理証明システムの証明規則と変換(「戦術」)を、当時はPDP10マシン上で、簡潔かつ正確にプログラムするためです。 実用的な選択には、可変状態(証明状態を対話型システムに格納できるようにする)と 型推論システム(後にHindley-Milner型推論と呼ばれる)を含めることが含まれました。 OCaml(Leroy)を含む後のML方言でも、同様の実用主義のテーマが見られました。 そのテーマは言語設計と、OCaml C外部関数インターフェース(FFI)などのツールの両方で確認できます。

話題を今日に至るところまで進めていくと、1970年代に由来する重要なアイディアがF# 言語設計の中核を成し、日常の言語使用経験の中心となっています。 すべてのMLファミリー言語と同様に:

  • F# でサポートされている中心的なパラダイムは今もなお強く型付けされた関数型プログラミングです。
  • F# の中心的な活動は、型 (type X) と関数 (let f x = …) の定義にあり、これらの宣言は型推論され、自動的に一般化されます。
  • F# は、プログラミング自体の詳細ではなく、操作されるドメインに焦点が置かれているプログラミングモードをサポートすることを引き続き目的としています。

今日、「ドメイン駆動設計」に対するF# の長所を称賛する本が出版されています(Wlaschin、2017)。 その長所は、「ドメイン」がLCF論理の用語と定理の象徴的な表現であったMLの初期の役割からこれまでのところ取り除かれていません。 MLの「精神」はF# でも非常に活気があります。そのことはいつも意図されてきたことです。

1970年代から今日への飛躍は、コンピューティング業界の大きな変化の時代にわたります: 私たちはPDP-10からクラウドシステムへ、パンチカードから携帯電話へ、ラインエディターからツールが豊富なIDEへ、 小容量ストレージから大容量ストレージへ、ネットワークなしからユビキタスネットワークへと移行してきました。 本稿では、F# がどのように開発されたか、これが発生した業界および学術的背景、言語への直接的な影響、およびその独特の貢献について説明します。 この物語は、プログラミング言語設計における他の多くの歴史と交差しています。 そこでは、関数型プログラミング、オブジェクト指向プログラミング、型システム、ランタイム設計、 オペレーティングシステム、およびオープンソースソフトウェアの歴史が複雑に絡まりあっていますが、 中でも、1990年代初頭の「オブジェクト指向の津波」に対するいくつかの反応が、F# の起源の1つとして強調されています。 物語は必然的に不完全であり、主に筆者である言語設計者の個人的な観点から語られていることをお詫び申し上げます。 参考文献が提供されていない場合、本文は筆者の思い出に基づいて原資料として提供されています。

私たちは、プログラミング言語のMLファミリーの基本的な考え方、つまり型安全で、簡潔で、正確で、ドメイン指向の関数型プログラミングから始めました。 筆者の観点からは、この考えはこの変化の時代を通して「強く、真実でありつづけた」と考えています。 それが頑固性によるものであるか、一貫性によるものであるか、それとも偶然によるものであるかは、読者に評価をお任せします。

2018年のF# とは

2018年現在、F# はそのドキュメントページで「.NET上で動作する関数型プログラミング言語」として説明されています。 F# 言語ガイド1では、この言語の次のような主要機能について言及しています:

  • 関数とモジュール
  • パイプラインと合成
  • リスト、配列、シーケンス
  • パターンマッチング
  • アクティブパターン
  • 型推論
  • 再帰関数
  • クォート
  • レコード型、判別共用体
  • オプション型
  • 測定単位
  • オブジェクトプログラミング
  • 非同期プログラミング
  • コンピュテーション式
  • 型プロバイダー

当ドキュメンテーションにはF# プログラミングのために利用可能な主要なツールとライブラリーの説明が続けて記載されています。 それには以下のものが含まれます:

  • クロスプラットフォームでのコンパイルと実行
  • 主要なF# および.NETライブラリー
  • Web、モバイル、およびデータプログラミングツールキット
  • Emacs、Visual Studio、VS Code、JetBrains Rider(TM)などの編集ツール。
  • ドキュメントを提供している会社のクラウドプラットフォームでF# を使用する方法。

F# プログラミングを学ぶための他のリソースは、同様の説明の順序に従います。 例えば、Fable(García-Caro、2018)は、クライアントサイドのWebプログラミングをJavaScriptにコンパイルするためのF# のパッケージです。 WebSharper(Granicz、2018)とSAFE-Stack2は、クライアントとサーバーの両方のコンポーネントが同じ言語で書かれている「フルスタック」言語としてのF# の使用を強調しています。

以上が現在のF# の姿です: オープンソースで、クロスプラットフォームで、強く型付けされた、簡潔なプログラミング言語で、さまざまなプログラミングシナリオに幅広く適用でき、ユーザーからとても愛されています。 言語コミュニティは、米国の非営利団体であるF# Software Foundation(FSSF)3、そしてTwitterなどのソーシャルメディアを中心にしています。 F# はさまざまなものに影響を与えました -- 最も直接的なのはC#ですが、それだけでなく、より広範にもです -- 結論の項ではこれについて説明します。 しかし、どうやってそこにたどり着いたのでしょうか?

背景:言語、Microsoftでのプログラム可能性、そして.NETの創造

1970年代から80年代にかけて、トランジスタの設計やチップの製造からソフトウェアの開発やアプリケーションに至るまで、コンピューター業界は急速に拡大し続けていました。 BASIC、PASCAL、Prolog、Modula 2、Cなど、さまざまなプログラミングパラダイムや言語の開発と採用に伴い、ソフトウェア開発ツールも急成長し、統合されました。 それぞれに付随するものが市販されていました(Visual Basic、Turbo Pascal、Borland Cなど)。 Logoのような言語は、プログラミングが「異なる」4ことがあり、大胆な新時代の「第4世代言語」が約束されているという新世代の想像力を刺激するのに役立ちました。

同時期に、Microsoftもまた、オペレーティングシステムとアプリケーションの会社として大規模な拡大を経験しました。 Microsoftは1975年にプログラミングツールを構築することから始めました。 プログラミング性の重要性 -- 商業的かつ技術的な取り組みとして -- は、同社とそのCEOであるBill Gatesの「骨の中」にありました(Microsoft、2012)。 1980年代を通じて、プログラミング性に関する彼の主な関心事は、商業的なものでした。 それは、DOSおよびWindowsエコシステム用のアプリケーションおよび独立系ソフトウェアベンダー(ISV)の商用エコシステムの作成方法をサポートする方法です。 最も重要だったのは、これらのプラットフォームを使用している開発者の数が非常に多いことでした。開発者がこれらのエコシステムの成長に貢献するからです。 同社は、マスデベロッパ市場を満たすためのVisual Basicや、よりハードコアな開発者向けのCのバージョンなどのツールを開発しました。 これは、後に "Mort" (Visual Basic)と "Einstein" (C++)のためのツール5として特徴付けられました。 そのようなツールはHyperCard6やToolBook7などの無数の急速な開発環境に対抗し、Microsoftはハンズダウンに成功し、 世界中でアプリケーション開発を主導し、オペレーティングシステムで独占的地位を獲得しました。 MicrosoftはFoxProやFORTRANコンパイラー8など、他にも数多くのプログラミングツールを製造していましたが、後に製造中止となりました。

1980年代後半には、「オブジェクト指向」プログラミングをめぐる新しい考え方の波が合体し、これがアプリケーションソフトウェア開発や学術界でますます影響力を帯びてきました。 確かに、オブジェクト指向はソフトウェア開発の概念化の周辺領域から中心となる方向へと移行しました。 市販のツールチェーンを持つ言語のパターンが繰り返されました。 例としては、1985年の最初のC++ 商用コンパイラー、1992年のBorland C++ 、1993年のIBM Smalltalkなどがあります。 OOを推進する要因の中で最も重要なものは、ソフトウェアにおけるユーザーインターフェース要素の普及です。 アプリケーションはインタラクティブになり、「ボタン」やその他の「ウィジェット」でできていました。 これらのウィジェットは、状態と動作を組み合わせた「オブジェクト」として簡単に概念化され、これらのウィジェットは階層的に分類できました。 手続き指向言語ではそのような抽象化をコードで直接表現することはできず、サブタイプなしの言語ではウィジェット間の必要な関係を表現することは困難であることがわかりました。 人々は2つの主要な質問を尋ねることによって言語を評価しました:「それは継承をサポートしますか?」と「すべてはオブジェクトですか?」です。 これらの基準を満たさなかった言語は、すぐに主流から取り残され忘れ去られるようになりました。

ソフトウェア開発方法論のこの新しい波とオペレーティングシステム会社との間の、業界を変えてしまうような関連性の見通しは、興味をそそるほど近くに描かれました。 たとえば、1993年のNEXTStep 3.0の発売では、NEXTStep OSが何らかの形でサポートしているという概念として「オブジェクト」に重点が置かれ(技術的詳細は漠然としていました)、 OSの洗練さと技術的な成熟度を示すためにJobsによって使用されました。 Javaが1991年から95年に開発され、1996年にリリースされたとき、それは少なくとも5つの点でMicrosoftにとって大きな挑戦でした。

  • Javaはオブジェクト指向で「現代的」でした。
  • Javaは、理論的には特定のオペレーティングシステムへの依存を減らすことができるWrite Once Run Anywhereソフトウェア開発を約束しました。
  • Javaは、高性能オペレーティングシステム市場の直接のライバルによって開発されました。
  • JavaはWebの黎明期におけるWebテクノロジとして位置付けられており、ブラウザーを介して最終用途のアプリケーションを提供する可能性があります。
  • Javaは仮想マシン(VM)やガベージコレクション(GC)などの一連の技術的なデバイスを使用していましたが、以前は比較的主流ではなく、 まだMicrosoftのプログラミング製品では提供されていませんでした。そして
  • Javaは応用学術コンピューターサイエンスへの貢献として認められ9、Microsoftではほとんど無視されてきた支持者を迎え入れました。 その結果、Javaは型付きオブジェクト指向の事実上の標準として採用されるようになりました。

Microsoftは当初、対応が遅れました。 社内では、同社は主力製品を実装するためにCにコミットしていましたが、同様にたくさんのアセンブリコードも持っていました。 ターゲットハードウェアの仕様を考えると、Javaのようにヒープを割り当てる「おもちゃ」の言語でWindowsやMicrosoft Wordを書くのは現実的ではなかったので、 JavaはすぐにはMicrosoftの内部使用の主要言語にはなりませんでした。 さらに、Visual Basicのような外部向けのRAD環境は、クラス指向言語で見られるOOへの構造化アプローチからすぐには恩恵を受けませんでした。 Javaの大流行が業界を襲ったため、Microsoftは1996年にSunからライセンスを受けたJava(Microsoft J++)を採用することで対応しましたが、 その後言語を拡張したため業界を揺るがす法的措置に直面しました。 これは、2001年の法務省同意判決の背景の一部を形成しました。

1997年、Microsoftは取り組みを変更し、 Javaの根本的な課題に取り組むことができると同時にWindowsのプログラミング性に固有のニーズにも取り組むことができる新しいプログラミングプラットフォームの内部開発を開始しました。 当初COM+ 2.0、またはDCOM、またはLightning、そして最終的には.NETと呼ばれていましたが、ランタイム環境の基本原則は次のとおりです。

  • それはVisual Basic、C++ およびJavaを含む複数のプログラミング言語をサポートするでしょう。 さらに、Anders Hejlsbergの設計のもと、最初はCool、その後C# と呼ばれる新しい言語が開発されました。
  • バイトコード、ガベージコレクション、JITコンパイル、そしてスタックベースのセキュリティチェックやリモート処理などの「ミドルウェア」機能をサポートするでしょう。 さらに、ランタイムは符号なし整数、ボックス化されていない表現、そしてインストール時のコンパイルをサポートするでしょう。
  • それは、CベースのWin32 APIへのネイティブな相互運用性やCOMの組み込みサポートなど、特にWindows上でのアプリケーション開発のために作られるでしょう。 ただし、十分に一般化され、他のオペレーティングシステムへの移植が理論的に可能にもなるでしょう。
  • そのSDKは無料で提供され、1992年に設立されたMicrosoft Researchによって管理されていた学術関係における新たな取り組みに合わせたものになるでしょう。

Lightningに関する決定は、Bill Gatesによって定期的にレビューされました。 2人の「開発者エバンジェリスト」 -- PeterとJames Plamondon10 -- の努力により、重要な決定が下されました。 すなわち、Lightningは、Microsoftが決定した一連の固定言語ではなく、多言語のためのランタイムだということです。 "Project 7" というアウトリーチプロジェクトが開始されました。 その目的は、Lightningのローンチ時に、7つの商用言語と7つの学術言語がLightningをターゲットにすることでした。 ある意味でこれはマーケティング活動でしたが、深い信念と意図もありました。 学術言語の定義を支援するために、James PlamondonはMicrosoft Research(MSR)に目を向けました。

F# の歴史の観点からすると、これはコンピューターサイエンスの歴史におけるほとんど無関係の伝統が融合し絡み合い始めた瞬間です:Robin MilnerとBill Gatesの世界が出会い始めました。

MSRは1992年に設立され、1997年9月に英国のケンブリッジに拡大されました。 Andy Gordon(プログラミング言語理論の著名な若手研究者)とLuca Cardelli(最初のML実装の1人で多作の研究者)が雇われ、 それから1998年9月、Simon Peyton Jones(Haskellの主な貢献者)、Nick Benton(MLjの理論と創始者、後述)、 Cedric Fournet(OCamlチームの中心的メンバー)、Sir Tony Hoare(世界的に有名なコンピューター科学者)、 Syme(本稿の筆者、オーストラリアでMLの初期貢献者であるMalcolm Neweyに指導を受けた学部生、そして後にF# の設計者、 関数型プログラミング、形式的検証およびJavaのバックグラウンドを持つ)など、 MSRのさまざまな拠点において、500人を超える研究者およびエンジニアが後に続きました。

突然Microsoftは学術的なコンピューター科学者たちを溢れさせていましたが、彼らは「プロダクトチーム」とは別の「組織」の中にいました。 多くの人がMicrosoftの製品範囲に影響を及ぼしたがっていましたが、 それはBell Labs(Cardelli)、DEC-SRC(Cardelli)、Compaq(Gordon)、およびIntel(Syme)において、このような研究室が「生計を立てた」方法であるという文化的記憶があったからです。 各研究者はそれぞれ独自の観点からコンピューターサイエンスの観点について深く伝道的であり、学術界の対応するコミュニティに対して部族的な忠誠心を持つことが多かったのですが、 その両方が製品チームとのやり取りや選択したプロジェクトを形作りました。 形式検証と理論分野における研究者の多くは、強く型付けされた関数型プログラミングの経験がありました。 ML言語ファミリーの創始者であるRobin Milnerは、「道の向かい側」のケンブリッジ大学の部長であり、研究分野の先駆者として高い評価を受けていました。

その一方で、Microsoftは多言語ランタイムに深く関わっていて、積極的に革新するように見られたいというフェーズに入っていました。 Lightningは既に典型的な関数型言語の実装の中心的な要素(GC、JIT、バイトコード)を多く持っており、 当初はWindowsオペレーティングシステムの範囲内でしたが、プログラミングでは異なるテーマを統合することを約束しました。 舞台は面白いことが起こるように整えられました。 Lightningの取り組みはNGWSと改名され、その後2000年の発売時に.NETと呼ばれるようになりました。

背景:1990年代における強く型付けされた関数型プログラミング -- Calculi、Miranda、OCaml、Haskell、Pizza

Microsoftが1990年代初頭に独占的な立場を確立し、オブジェクト指向が世界を席巻していた一方で、 強く型付けされた関数型プログラミングの世界は小さく、取り残されながらも活発で活気に満ちていました。 この世界は、私たちが今「プログラミング言語研究(PL Research)」と呼ぶ他の活動分野と重なっていましたが、 当時は形式的検証、型理論、プログラミング論理、そして適用が広がる圏論が含まれていました。 この世界は基本的な計算、つまり一番わかりやすいのはラムダ計算とシステムFのようなその派生ですが、 他にもCCSやπ計算(Sangiorg & Walker、2001)のような並行計算によっても大きな影響を受けました。 統一オブジェクト計算を見出すための努力は順調に行われており(Cardelli & Abadi、1996)、FOOLのような会議は、 既存の言語に新しい構成体が追加されているものについての基本的な形式を探しました11

「形式手法」は、形式化されたハードウェアとソフトウェアに関する政府の主導による、1980年代の当時の重複分野でした。 業界における形式的方法の論争(MacKenzie、2001)および比較的謙虚な成功によって、 1990年代の研究者はモデル検査や静的分析ツールを含むバグ発見のためのより実用的な手法に注目しました。 SMV, Z, ACL, HOL88, PVS, HOL90, Isabelleおよび商業製品などのシステムを使用して、ソフトウェアおよびハードウェア設計の側面がモデル化され、形式化され、検証されました。 これらのシステムの実装とスクリプト作成には、関数型言語、たとえばEdinburgh ML(HOL88)、Standard ML(HOL90、Isabelle)、OCaml(Coq、NuPRL)、 Caml Light(HOL-Lite)、LISP(ACL2、PVS)がよく使用されました。 このように、これらのシステムは、強く型付けされた関数型言語の採用の中核的要素を形成し、関数型プログラミングをより理論的なコミュニティの近くにとどめました。 Standard MLの形式的定義(Harper, Milner, & Tofte、1990)とその解説は、標準化、協力、形式主義、理論の美徳を祀っている、ほとんど聖なるテキストとして見られていました。 同時に、いくつかの関数型プログラミングシステム、例えばParallel ML(Rabhi & Gorlatch、2003)やHaskellの並列版などは、並列プログラミングの研究と密接に連携していました。 これらが一緒になって、本稿の筆者が学部時代の研究で強く型付けされた関数型プログラミングとMLに最初に遭遇したという文脈を形成しました(Syme、1993)。

1994年に発見されたIntelのFDIVバグ12により、形式検証に対するハードウェア製造業者側の投資が大幅に増加しました。 インテルは学術界に助けを求めましたが、その中から、Carl Seger氏が率いるForteが選ばれました。 ForteはBDDとIEEEモデルまでの浮動小数点回路のデータパスを検証するための定理を証明するツールチェーンで、 Forte FLと呼ばれる強く型付けされた関数型言語を中心に構築されています。 プログラミング言語の設計にはそれ以外の影響はありませんが、このことが言及されているのは、1996-97年に筆者がこのプロジェクトのインターンとして雇われ、 その文脈で応用形式検証における記号操作のための「グルー言語」として強く型付けされたFPの極端な効果を経験したからです。 なお、それはF# の初期の応用分野でもあります(Segerら、2005)。 Forte FLは、外部データと相互運用する場合や、強く型付けされた言語の設計に関するクォートを含める場合など、実用的な選択も多く行いました。 この経験は後のF# 設計に大きな影響を与えました。

強く型付けされたFPは、1985年に最初にリリースされたMiranda13でも重要な用途を見せました。 1990年代には、強く型付けされた関数型プログラミングの小さな世界も、活発な研究コミュニティによくある経緯で分裂しました。 Haskell 98は、怠惰で純粋な関数型プログラミングの流れを統合しました。前身はHOPEとMirandaでした。 1989年からのStandard MLは、関数と命令が混在する言語の統一的な取り組みとして残っています。 しかし、INRIA Project Cristalグループは標準化を時期尚早と見なし、その代わりにCaml Lightを作成し、次にOCaml14を作成しました。 Standard ML自体は、その革新的なモジュールシステムと密接に関連しており、Poly MLおよびNew JerseyのStandard MLで実用的な実装が行われていました。

強く型付けされたFP言語とコンパイラーは、関心、採用、そして使用に関して、細流化を続けています。 C、C++、およびJavaの大規模な採用に挑戦するには十分ではなく、業界ではほとんど知られていませんが、言語を維持し、研究を推進し、 OCaml、Standard MLおよびHaskellの熱心な支持者の小さな群15を作成するのに十分です。 幸運にもこれらの言語を実際に使用した人々(筆者を含む)は、生産性の劇的な向上といくつかのフラストレーションを経験しました。 オリジナルのMLの実装と同様に、使用されるドメインは通常ある種のシンボリックプログラミングでした。 高い生産性を経験できるのは、提供されている機能の組み合わせの独特の有効性によるものです: それは、安全な合成プログラミングをサポートするためのHindley-Milner型推論の「魔法」、ドメインデータを記述および操作するためのパラメトリック多相(ジェネリクス)、 判別共用体の有効性、蔓延するnull値がないプログラミングの正当性の利点、コードと形式モデルの密接な対応などです。 これらに加えて、表現指向プログラミングの優雅さと表現力があります。それはLISPの頃からよく知られていたものですが、喜びと感動をもって新たに再発見するユーザーが相次ぎました。 これらの言語がもっと広く使用される可能性があること、そして価値のあるプログラミング技術がJavaの広範な採用によって失われつつあるという強い思いがありました。

1990年代初頭のオブジェクト指向への関心の波は産業界と同様に学界にも大きな影響を与えました。 1990年代半ばまでに、FPおよびプログラミング言語の世界の多くは、C++ 、Java、およびOO全般の出現によって、本当にショックを受け、当惑し、混乱を招き、一部のケースでは幻滅を感じました。 反応は様々でしたが、私たちは今、2000年代のF# 、Scala、その他の言語の起源を理解するための鍵となるOOの大波への反応を調べています。

オブジェクト指向に対する1つの応答は、「降参」してJava実装に取り組むことでした。 他にはJavaのまわりの形式化に取り組んだ人たちもおり、実際に筆者は当初、博士論文でまさにそのことをしました(Syme、1999)。 そして他の人たちは基礎的なオブジェクト計算を定式化し出版しました。 オブジェクト指向の機能をFP言語に統合することで対応した人もいます: LISPはすでにCLOS(Common LISPオブジェクトシステム)を追加していましたし、 OCamlは魅力的なオブジェクトシステムの基礎として使用される新しい形式の一般性( "row polymorphism" と "column polymorphism" )16を導入しました。

別の回答は、強く型付けされた関数型言語に関連する特定の技術的特徴を「主流の」オブジェクト指向言語に統合することを提案することでした。 WadlerとOderskyは、パラメトリック多相(ジェネリクス)、判別共用体、およびファーストクラスの関数値を組み込んだ Javaの変形であるPizzaの開発を担当しました(Bracha, Odersky, Stoutamire, & Wadler、1998)。 これはその後、Generic Java(GJ)の提案に切り詰められ、その後C# 、Scala、およびF# に大きな影響を与えました。 最終的にGJはJavaジェネリクスの基礎となりましたが、「型消去」の使用と正確な実行時型情報の欠如は重大な妥協点でした。

また別の角度からのアプローチは、関数型プログラミング自体を「分解」して、根本的な問題を調べることでした(例えば、HaskellまたはStandard MLの実装によって示されるように)。 その一例が、 なぜ誰も関数型言語を使わないのか という論文でした(Wadler、なぜ誰も関数型言語を使わないのか、1998)。 この文書は、広く引用されてはいませんが、筆者が1998年にMicrosoft Researchで仕事を始めたときの、プログラミング言語の分野に対する理解の中心となっていました。 Wadlerの論文は、下賤な大衆の無知を非難するのではなく、その時点で強く型付けされたFP実装の7つの問題を概説しています: それは、ライブラリー移植性可用性パッケージ性ツールトレーニング人気度 です。 また、関数型言語が使われない理由ではないものとして 性能 および 無知 を列挙しています。 F# の初期の開発は、本質的にこれらそれぞれに対処するための努力でした。

さらに、Poly MLやHarlequin MLなど、強く型付けされたFP言語の新しい商用実装を介して競争しようとした人たちもいました。 しかし、これらはほとんど採用されず、業界の「大企業」の支援が必要であると感じてコミュニティを去りました。

最後の対応は、確立された関数型プログラミング言語を実装するための基盤としてJVMを使用し、 それによってFPをブラウザーおよびWebに配信する手段とすることでした(当時はそれがJavaの背後にある初期の原動力でした)。 これらの取り組みの中で最も重要なのは、 PersimmonでのBenton、KennedyらによるStandard MLの研究/商業的実装であるMLjでした(Benton & Kennedy、涙なしでの言語間作業:SMLとJavaのブレンド、1999)。 MLjはプログラム全体のコンパイラーで、オブジェクトプログラミング拡張機能を介してJavaエコシステムと相互運用できました。 Persimmonの研究部門が1998年に畳まれたとき、BentonはMSR Cambridgeに移動し、その後Kennedyも後を追いました。 これは.NETおよびそれ以降のF# に関連性の高い経験をもたらしました。 これらのさまざまな反応にもかかわらず、理論コミュニティではオブジェクト指向への強い論争がありました。 OOの支持者は異端の汚名であまりにも容易にラベル付けされました:「節操のないナンセンス」、「理論的根拠の欠如」などです。

筆者が1998年にMicrosoft Researchに参加し、F# に至る前身の作業を開始したことで、これで総合的な周囲の状況の概要が完成しました。 完全を期すために、筆者自身に対する背景の影響は次のとおりです。

  • 筆者は、主に定理証明システム(HOL88のEdinburgh ML、HOL 90のNew JerseyのStandard ML、HOL-LiteのCaml-Light、IntelのForteFL)のコンテキストで、 強く型付けされた関数型プログラミングを使用しました。 それらの弱点を認めながら、彼はそれらを愛するようになりました。 学部時代の仕事で、彼はMLの創始者の一人、Malcolm Neweyによって監督されていました。 博士課程の仕事、OCamlコミュニティ、およびMSR Cambridgeを通じて、筆者は、強く型付けされた関数型プログラミングを標準と見なしている、重複するコミュニティに関わっていました。
  • 筆者は、JavaとJVMの形式化の研究を含む論文の仕事の一部として、オブジェクト指向言語(C++ 、Java)を使用していました。 1992年の大学でのC++ に関する彼の経験は、特に学生プロジェクトでの階層分類の過剰使用を通じて、否定的でした。
  • 子供時代、1980-87年に、筆者はBASICとLogo(Apple II)とTurbo Pascal(Windows)を使いました。 学生時代に、彼はProlog、C、Scheme、Modula 2を使いました。 比較プログラミング言語コースは、幅広い言語に興味を起こさせました。 仕事を始めた早い時期に、彼はオーストラリアのソフトウェア会社でWindows上のPrologを使っていました(SoftLaw、1990-1993)。
  • 筆者は、博士論文の一部として、SMLNJ、MoscowML、Caml-light、OCamlを含むさまざまなMLの方言やツールチェーンを使い、 強く型付けされた言語、証明および編集システムをいくつか実装しました。 さらに彼は、当時はやや変わっていましたが、これらのシステムのためのビジュアルツール、 特にHOL90用のグラフィカル校正編集IDE(Syme、1995)と定理証明者DECLARE用の校正編集ワークベンチ(Syme、1999)も実装しました。 筆者はIDEツールに前向きな気持ちを持ち、IDEツールと言語設計の間の相互作用を理解しました。
  • 1996-98年に、筆者は、OOと関数型プログラミングを融合するという、Drossopoulou、Leroy、Wadler、Oderskyなどの学術的リーダーの仕事に触れていました(Alves-Foss、1999)。
  • 筆者は、強く型付けされた関数型プログラミングを「大衆」にどのように提供するかを想像しようとする議論に参加していました。

Project 7 と .NETのジェネリクス

Project 7がMicrosoftで開始されたとき、MSR Cambridgeの研究者は学術的な流れを含めるために次の言語を推奨しました: Eiffel, Mercury, Standard ML, OCaml, Scheme, AliceそしてHaskellです。 これを見ると、MSRの研究グループの偏向ははっきりしています:7つの推薦のうち6つは強く型付けされた言語であり、7つのうち3つは狭い意味で「強く型付けされた関数型言語」です。 狭い意味というのは、例えば Hindley-Milner型推論を取り入れ、ファーストクラスの値としての関数を持つということです。 Project 7の商用言語には、Perl、Python、Cobol、Adaが含まれていました。 それぞれに学術的または商業的なパートナーが見つかり、資金はMicrosoftから提供され、ワークショップはMSR Cambridgeなどで開催されました。

振り返ってみると、Project 7には欠陥がありましたが壊滅的ではありませんでした -- プロジェクトに従事しない研究者が何人かいましたし、言語実装の中にはあまり使用されていなかったものがありましたし、すべての言語処理系を維持していくのは高コストでした。 現在でもCOBOL.NETを購入して使用することができるとはいえ、.NETプログラミングはMicrosoftがサポートする言語であるC# 、Visual Basic、およびF# によって支配されており、 JVMの多言語エコシステムの方がより活気があります。 しかし、Project 7は明確な技術的影響を与えました。 たとえば、この段階でGordonとPeyton Jonesは.NETの設計者と協力し、これらの言語のいくつかをサポートするため、および.NETバイトコードをJVMから区別する方法として、 末尾呼び出しをファーストクラスの操作として含めるという議論に勝ちました(.NETバイトコードには "tail." 命令が含まれています)。 これにより、.NETはプラットフォームにもたらされる言語の要求によって導かれた、技術革新と差別化という長い技術的道筋をたどり始めました17

Project 7はまた、「言語の相互運用性」の問題を提起することによっても影響を及ぼしました。 つまり、共通の基盤をターゲットとする言語を複数得ることと、それらを相互運用させることはまた別の問題だということです。 1999年に、筆者とその同僚は、次のように主張している内部ホワイトペーパー「COM+ VOSに対する拡張機能の提案」18を執筆しました。

COM+ランタイムの主な目的は、他の潜在的なバックエンドランタイム環境によって提供されるものよりも技術的に明らかに優れたサービスとパフォーマンスを提供することです。19

そしてホワイトペーパーは、Microsoftが「言語革新に真剣に取り組むべきだ」とも主張しました。 5つの技術的特徴が提案されましたが、そのうち「一般化されたデリゲート」(すなわち、ファーストクラスの値としての関数)と「強化されたパラメトリック多相」がより重要でした。 ここではPizzaとGJの影響が強く、この2者は競争相手として明確に言及されていました。 筆者はまた、これらの機能を組み込んだ.NETバイトコードの拡張であるILXも開発しました。 これは、他のProject 7言語で採用されることを望み、当初は型消去を行って既存の.NET ILにコンパイルするという方法で.NET上に実装されていました。

このホワイトペーパーは、C# とEiffel、OCaml、Haskellなどの他のProject 7言語の両方で機能するような形式のジェネリクスを.NETに提供することを目的として設計された ".NET Generics" プロジェクトのきっかけとなりました。 .NET Genericsとその歴史は他の場所20でも取り上げられていますが、 その後4年間でSyme、Kennedy、Russoは.NET GenericsをC# と.NETで提供するために多大な努力を払ってきました(Kennedy & Syme、2001)。 この機能はMicrosoftのさまざまな部署からの熱意、敬意、無関心に遭遇しましたが、2001年のGatesのレビューは好評を博し、物事を好転させ始めました21。 最終的に、この機能は2005年に .NET 2.0 "Whidbey" リリースの一部として提供されました。 同時に、Microsoftはオープンソースを採用するための最初の非常に暫定的なステップを開始し、 .NETコードベースの「シェアードソース」版リリースであるRotorが作られました。 それとともに、.NET Generics実装を含んだ、Gyroと呼ばれるRotor拡張も作成されました。 MSRの社内展示会 "Tech Fest" のポスターを図1に示します。

Figure 1 -- TechFest 2002(Microsoft Building 33, Redmond)での.NET Genericsポスター

.NET Genericsの重要な前提は、実行時型情報の管理や、新たに発生した具象化用の新しいコードのJITコンパイルなど、ジェネリクスの具象化をランタイム環境が「管理」できることです。 それにより、C# などのエンドプログラミングモデルは、プログラマーの観点から見て非常に完成された滑らかなジェネリクスの形式をサポートできます。 つまり、実行時型情報は正確で、具象化された型の作成と管理のプロセスは邪魔にならず、具象化のコードはポリシーに基づいて自動的に共有されます。 .NET Genericsは非常に成功しています:まず、何百万というC# 、F# およびVisual Basicプログラマーによって広く採用されています。 次に、.NET GenericsはC# とJavaを区別する重要な要因と見なされています。 そして、F# 、C# 、および.NETで提供された、後の多くの革新の基礎となっています。 たとえば、ジェネリックコレクション(C# 2.0)、LINQ(C# 3.0)、タスク(C# 4.0)、async / await(C# 5.0)、Span(C# 7.2)は、すべてF# 機能と同様に.NET Genericsを多用しています。 .NETに時代の数年先を進ませた、言語設計および実装における画期的な瞬間として.NET Genericsを見る根拠があります。 現在においても、Java、Go、Scala、Swiftなどのシステムは汎用性の実装と闘っています。 同時に、ジェネリックスは、Microsoftの.NET実装を発展させるのに多大なコストがかかる技術的機能でもあります。 ジェネリクスはJITを介して最も簡単に実装されましたが、.NETコードの完全に静的なコンパイルを行おうとする試みはこの機能に苦労しています。

F#(まだ存在していませんでした) の歴史の観点からは、.NET Genericsのデリバリーが成功したことで、 .NETは意図的に、強く型付けされた関数型言語から.NETバイトコードへの「直接」コンパイルに適した基盤に変わりました。 これは偶然ではなく設計判断を伴ったものです。 たとえば、Hindley-Milner型推論によって推論された汎用性を、実行時のオーバーヘッドをほとんどまたはまったく伴わずに.NET Genericsに直接コンパイルすることが簡単にできました。 MLのような方言で書かれた、次のような単純なコードを考えてください。

let keyAndData getKey x = (getKey x, x)
let data = [| 1 .. 100 |]
let add x = x + 1
let y = Array.map (keyAndData add) data

ジェネリック化された型注釈付きの形式では、このコードはおおよそ次のようになります。 暗黙の一般化のポイントを示すために <T> 疑似表記を使用しています。

let keyAndData<T,U> (getKey: T -> U) (x: T) : Pair<U, T> = (getKey x, x)
let data : array<int> = [| 1 .. 100 |]
let add (x: int) : int = x % 7
let y = Array.map (fun x -> keyAndData<int,int> add x) data

GJのような多くのジェネリクスシステムでは、TUのようなジェネリック型の値はボックス化(ヒープ割り当て)された形式で表現されることでしょう。 したがって、他の最適化がない場合、上記のコードでは、(ジェネリックな) "keyAndData" 関数に入るときに整数のボックス化が行われ、 (非ジェネリックな) "add" 関数に渡されるときにボックス化解除されます。 基本的なコレクション型に対するこのような暗黙のコストは耐え難いものであり、Hindley-Milner型推論言語を.NET上で本質的に低パフォーマンスにしてしまいかねません。 .NET Genericsを使えば、これらの特定のパフォーマンスの問題は解消されます。 .NET Genericsは、後にF# を生み出すための非常に重要な基礎を築きました。

F# を作成する決定

MSRでは、Project 7がSML.NETプロジェクトにもつながりました(Benton, Kennedy, & Russo、2004)。 SML.NETは前述のMLjの続きであり、.NETを対象に変更されたものでした。 SML.NETは、仮想化解除と表現変換を備えた洗練されたプログラム全体のオプティマイザーを使用し、オブジェクトプログラミングの拡張機能を備えたStandard MLの忠実な実装でした。 システムは高品質でしたが、外部のマインドシェアを多く得ることはありませんでした。 2001年に、筆者はSML.NETに不満を抱いていました。SML.NETは、.NET自体がすでに公開されても、まだリリースされていませんでした。 同僚の研究目標は十分に尊重してはいましたが、筆者は1998年にWadlerによって特定された7つの主要なテーマに取り組むために、 強く型付けされたFPが多くのプログラマーによって容易に採用されることができる方法で届けられるのを見たがっていたのでした。 その際、Camlの実装が筆者に影響を与えました:OCamlは比較的直接的で簡単なコンパイル戦略を使用していて、なぜプログラム全体のコンパイル戦略が必要であるかは明確ではありませんでした。 一方で、SML.NETは.NET Genericsをターゲットにしておらず、そのようにする明確な計画もありませんでした: SML.NETコンパイラーは、パフォーマンスとコンパクトなコードの回復を目的として、プログラム全体のコンパイルと広範なモノモーフィゼーションの利点を前提としていました。 研究室で一般的に起こるように、意見の相違が起こりました。

当初、筆者はReuben Thomasと共同で、Glasgow Haskell Compiler(GHC)の「コア」中間表現から.NETバイトコードへ直接変換することで、Haskell for .NETの実装を試みました。 この経験は部分的に成功しました:小さなプログラムなら動きました。 しかし、筆者はSimon Peyton Jonesの助言を受け、Haskell.NETはいくつかの技術的および文化的な理由で成功することはできないと信じるようになりました22

  • 他のProject 7言語と同様、Haskellを.NET上で「単独で」実行するだけでは十分ではありませんでした。 主な目的は、.NETライブラリーと完全に相互運用できる、.NETエコシステムの一部である関数型言語を作成することだったからです。
  • 完全な相互運用とは、すべての.NET関数がHaskellでHaskellの型を用いるようにレンダリングされる必要があることを意味するので、型変換が必要です。 両者の型システムは同じではなかったので、変換は面倒で、多くの場合は単に変換不能だったりします。
  • さらに、変換を容易にするためには、何らかの形式のサブタイピングとオブジェクトプログラミングに対応できるようにHaskell自体を改造する必要があったでしょうし、 最終的には既存の.NETクラスを拡張する機能も必要となったでしょう。 Haskellコミュニティは、特定のプラットフォームの要件によって引き起こされるそのような言語の大幅な変更を検討することに消極的でした。
  • 当時、ほとんどすべてのHaskellコード(ライブラリーを含む場合)には、対応する.NET側のサポートが欠けている技術的な機能が必要でした。 高カインド型変数や、軽量スレッドや、例外(Haskellの例外セマンティクスをもつもの)や、 エフェメロン(訳注:弱参照キーのテーブル)や、ソフトウェアトランザクショナルメモリーなどです。 したがって、相互運用はさておくとしても、どんなHaskellプログラムも.NET上でうまく動くと主張するのは無理があり、サブセットしかうまく動かなかったでしょう。

そのため、Haskell.NETの開発は中止されました。

OCamlとJVM/.NETの問題もこの頃のCamlメーリングリストで議論されていました。 たとえば、次のメッセージは2001年2月6日に筆者が送信したものです。

件名: OCaml on CLR/JVM? (Was RE: OCaml <--> ODBC/SQL Server)

ちょっと探しても見つからないのは、OCamlでODBCデータソースを使って問い合わせたりインターフェースしたりする簡単な方法です…

今、私は言うまでもないことを言わなければなりません: CamlがJavaまたは.NET Common Language Runtimeとシームレスにインターフェースをとることができれば素晴らしいことではないでしょうか? そうすれば、既存のライブラリーを利用するだけでよくなるので、このような質問や問題に直面し続ける必要がなくなるでしょうから。 私は、.NETバージョンのOCamlを目指して私と一緒に仕事をしたいと思う人がいるかどうかをすごく知りたいのです。 私はこの件についてこれまで何度もXavierと話し合ってきましたし、Haskellの.NETコンパイラーを作ったときに、コア言語のための基礎となる作業をたくさん行いました。 .NET上でCamlを動かして相互運用することに興味がある人は、あるいはその件について議論するメーリングリストに参加したいだけでもかまいませんので、連絡ください!23

これは、OCamlの.NETをターゲットにしたバージョンを作成したいという筆者の願望を初めて公にしたものです。 2001年2月8日にLeroy(訳注:Xavier Leroy、OCamlの開発リーダー)が返信しました。

私は、OCaml/Javaのインターフェースに取り組んだり取り組まなかったり(最近はほとんど取り組んでいませんが)しています。 その仕組みは、外部関数インターフェース(JavaはJNI、OCamlはCインターフェース)を介して2つのシステムをCレベルで結合するというものです。 これは、Haskell/Javaの同様なインターフェースに関するErik Meijerらの研究に強く影響されたものです (彼らHaskellの人たちは間違いなく言語の相互運用性の最先端にいます。これは、私が2番目に盗んだ相互運用性のアイディアです。最初はIDL/COMバインディングでした)。

低レベルの結合は驚くほど簡単です。2つのガベージコレクターを協調させることもできます。 というのは、JNIとOCamlのCインターフェースは、両者の実装を全く変更しなくても、結合を機能させるのに十分な機能を提供しているからです。なんて素敵なことでしょう。 唯一の制限は、クロスヒープサイクル(Javaオブジェクトを指すCamlブロックを指すJavaオブジェクト) は決して回収できないということです(これを指摘してくれたMartin Oderskyに感謝します)。

もちろん低レベルのインターフェースは型安全ではありませんから、本当にやりがいがあるのは、 JavaのクラスやオブジェクトをCamlのクラスやオブジェクトとして、あるいはその逆に見せる、型安全なビューを構築することです。 この件については、私はいまだにいくつかの問題に苦しんでいます。 たとえば、JavaのオブジェクトをCamlの抽象型の値にマッピングし、メソッドをそれら抽象型の関数として扱う方が、 JavaのオブジェクトをCamlのオブジェクトにマッピングするよりもはるかに単純(実装上のことで、エンドユーザーの使用感のことではありません!)だとわかりました。 それは全く予想外でした!

私が学んだことの1つは、言語の相互運用性に関する本当の問題は、 言語Xを仮想マシンYで動くようにコンパイルする方法(効率は良かったり悪かったりするでしょうが、これは常に行うことができます)ではなく、 Xのデータ構造とオブジェクトを、Yで動くようにコンパイルされる他のすべての言語Z1 ... Znのデータ構造とオブジェクトへマッピングする方法です。 今思えばそれは明白なのですが、多くの人(私自身も含む)がしばしばこの点を見落としており、 相互運用性のためには同じ仮想マシンにコンパイルすることが必要かつ十分であると信じているように思います。 実際にはそれは必要でも十分でもありません…

この作業はJVMで始めたものですが、.NET CLRがJNIと同等の機能を持つ外部関数インターフェースを持つようになれば、.NETでも動くようにできることは間違いありません (そして、いずれそうなるだろうと確信しています。そうする意味があるという理由だけではなく、Javaが持っている機能なら.NETも持ってないといけないだろうから :-) です)。 今後の開発をお待ちください。24

上記は、これまでに多くの言語が直面してきた基本的な問題を示しています。 ある言語は、自身のランタイムを保ち、.NETやJVMとは間接的に相互運用するべきでしょうか、それとも.NETやJVMのランタイムを直接ターゲットにするほうがいいのでしょうか?25 Leroyの返信には意見の相違がみられました: Project 7ではとても密接な相互運用性を想定していました。メモリー、コード、リフレクション、JIT、GC、およびライブラリー機能を含む1つの仮想マシンを共有することで、 ホスト側エコシステムのオブジェクトシステムを対象言語に組み込める可能性があるものです。 Leroyが説明したアプローチは、技術的には、既存のOCaml実装にとって非常に賢明なものでしたが、いざ.NETを想定した場合はしっくりきませんでした。 筆者には、言語間の境界で、パフォーマンス、相互運用性、ツールなどの問題に本質的に遭遇しそうに思われました。 そしてこのアプローチの採用は、.NETとOCamlの両方の実装に依存することを厭わない、共通部分に限定されるだろうとも。

この議論に関して、Standard MLのプロプライエタリー実装であるHarlequin ML26を実装したDave Berry (後にDaveはMSR Cambridgeと契約して.NET Genericsのオープンソース版を開発しました)から、彼の経験に基づいた寄稿も寄せられました。 2002年2月9日付けの投稿は以下の通りです。

今、私は言うまでもないことを言わなければなりません: CamlがJavaまたは.NET Common Language Runtimeとシームレスにインターフェースをとることができれば素晴らしいことではないでしょうか? そうすれば、既存のライブラリーを利用するだけでよくなるので、このような質問や問題に直面し続ける必要がなくなるでしょうから。

この見方は理解できますが、少々単純ではないかと思います。 …別の見方をすると、OCamlはすでにCと(少なくともネイティブコードのコンパイラーと)プラットフォームを共有しているので、すべてのCライブラリーはすでに利用可能です… それでもCライブラリーとリンクするのは大変な作業です。なぜJavaと.NETがもっと簡単だと言えるのでしょうか。 それに、MLjを使ったML/Javaシステムの構築に向けてなされた取り組みを見てください…。 スレッドは、潜在的に問題となりえるもう1つの分野です。実際、スレッドは全くの地雷原になる可能性があります。27

2002年2月10日に筆者が返信した内容は:

このビジョンを実現するにはかなりやるべきことがありますが、 原則として、クリーンな相互運用のストーリーは、他の人が書いた言語Xのコードを言語Yのライブラリーとして際限なく書き直すことを確実に上回るものです。 Project 7に関わっている私たちは、この相互運用を実現するための1つのアプローチ、すなわちMLjのように言語を.NET MS-ILに直接コンパイルし、 時には相互運用性を改善するために言語に拡張を追加することに取り組んでいます。 また、.NETインフラストラクチャの改善にも取り組んでおり、MS-ILにおけるパラメトリック多相などの機能のサポートを提案しています。

Xavierが述べたように、彼もOCamlのための解決策に取り組んでいます。 しかし、実際にものを動かすためにあなたが取るアプローチが何であっても、オブジェクトモデルの構成をMLやHaskellやOCamlにどう反映させるかという問題は変わりません。

私たちのアプローチの方が簡単になる理由はいくつかあります。 たとえば、Javaバイトコードに相当するMS-ILにコンパイルした場合、何の努力もせずに相互運用境界を越えて例外を伝播できる可能性があります。 バイトコードにコンパイルする場合は、たとえばMLのint64をCのint64と表現的に等価にするなどといった、表現の互換性をより多く保証することもできます。 バイトコードにコンパイルしない場合は、Camlの相互運用境界を越えるために整数すらマーシャライズする必要があることを忘れないでください。 自動化することができるとはいってもです。

Javaと.NETのオブジェクトモデルのセマンティクスはCと比べて非常にシンプルなので、オブジェクトの転送により一貫性を持たせることもできます。 たとえば、ポインタを "in-out" や "in" や "out" パラメーターとして解釈するためのIDLは不要です。

あるレベルまでは、Xavierのアプローチ、つまり2種類のランタイムやガベージコレクターなどを維持することが好きですが、 .NETアプローチの一部として想定されている(そして実際に現在C#、C++、VB.NETおよび他の.NET言語で使われている)多言語コンポーネントプログラミングにまで広げるのは困難です。 GCが2つあるだけでもすでに十分問題です(両方ともキャッシュを使い切るようにチューニングされているため、パフォーマンスが低下する可能性があります)が、 1つのプロセスに10言語のコンポーネントがある場合はどうなりますか?10個のGCが注意を払われるために競争するのですか? 機能するようにすることは不可能ではないでしょうが、1つのGCがコンピューティングインフラストラクチャの一部を形成し、そのサービスを共有することを受け入れるほうが、 概念的にはある種の明瞭さがあります。 こういった側面に関して、.NETアプローチには非常に説得力があると私は思います。

余談ですが、こういう言い方も面白い質問だとは思います。「OK、私たちの言語の最終目的はこんなコンポーネントを作成することだということに疑問の余地はないとしましょう。 そのインターフェースは、Javaまたは.NETの型システムで表現されていますが、OCamlとMLの機能と概念の単純さはできるだけそのままなのです。」というものです。 あなたが最終的に何を求めているのか私には正確にはわかりませんが、何かしらをC#やJavaから引き継ぐ言語になるのかもしれないと思います (あなたが興味を持っているものがそれであるなら…)。 ですが、Java/.NETコンポーネントの構築を最初から真剣に受け止めないと、ちょっとしたハックで終わってしまいかねないと感じているのです。 つまり面白く、使いやすいハックかもしれませんが、それほど 良い 言語ではないというものに。

私が見てきた中では、この種の作業で繰り返し起こる技術的問題の中でも最大のものはおそらく型推論の問題であり、 そしてJavaと.NETモデルの両方が、APIを受け入れやすくするためにサブタイプとオーバーロードの両方に依存しているという点です。 型推論は、サブタイプやオーバーロードのどちらでもうまく機能しません。 このことはもう本当に、とても残念なことです。なぜなら型推論は、生産性を向上させるためにMLが提供しなければならない主要なものの一つだということが明白だからです。

追伸:スレッドに関して -- あなたはスレッドの問題をまずいものと思っているかもしれませんが、私はその半分ほども悪いと思っていません。 最終的に、OCamlスレッドはある時点でWindowsスレッドにマッピングされます。 言語間でスレッドを共有することを意味なくさせるような、典型的なMLおよびCamlスレッドライブラリーの特別な論理プロパティがそれほど多いとは私には思えません (バイトコードにコンパイルするときに、非同期例外が物事を難しくしてしまうことは本当だとしても)。 とはいえ、この問題について私は専門家ではないことを認めます。28

最後には技術政治の論争もありました。今回は2002年2月12日のFabrice le Fessantからの回答を見てみます。

.NET VMはオープンソースなのですか?Microsoftに依存しない部分はどこですか?…

Microsoftが自社の新製品を使用してもらいたいのなら、自社のVMにもっと多くの言語を移植するのはMicrosoftの問題です。 こんな風に言うだけではだめです。「私たちは自家製の言語(C# 、C++、VB.NET)を(それらのために設計されていない)VMに移植しました。 ですので、このVMがユニバーサルVMだと証明できたわけです。さあ、あなたたちの言語も同じようにしてください。 そうしないと、私たちの顧客はもうあなたたちの言語を使わなくなるでしょう…」

それで、OCamlの.NET移植版なんて本当に必要なのですか?OCamlはWindows上でも、他の多くのOS上でも問題なく動作しているのに…29

オープンソース、標準、相互運用性、クロスプラットフォーム実行のメリットについて議論するスレッドが続きました。 それらはF# をもってしても13年間も解決できず、F# だけでなくC# と.NET Coreが最終的にオープンソースかつクロスプラットフォームになってやっと解決された問題でした。 Dave Berryによる2002年2月16日の寄稿はもっとポジティブでした。

Microsoftは、プログラミング言語研究者への働きかけに対し、褒められるべきだと思います。 私としては、MLをコンパイルするための優れたターゲットとなる、広く行き渡ったVMを歓迎するでしょう。 同じVM上の他の言語との相互運用性は、あれば嬉しい程度のおまけです…。 とは言っても、相互運用性は依然として困難です。…30

そこには正当な議論と用心深さがたくさんありました。 そして、筆者はOCamlとその既存のユーザーベースに対してきちんと敬意を払おうと決心したこの時点を起点として続行しました。 筆者はOCamlと、OCamlが示すプログラミングへのアプローチを本当に気に入っていたからです。

.NETなどのソフトウェアインフラストラクチャやアーキテクチャーの将来の軌道を予測することも、決定を下す際の重要な要素でした。 たとえば、2002年3月3日のArturo Borquezによる最後の返信がこちらです。

おそらく私は間違っていますが、本件について私が信じていることを述べさせてください。 …C# がVBの「質量」に達することは決してないので、C# はあまり重要ではありません。 …本当の問題は…クライアント/サーバーモデルです…。 私の意見では、このモデルには未来はありません。…クライアントは最小限になるからです…。 私の結論は、…CLR/JVMはCamlの将来にとって重要ではありません。どちらも死んでしまうからです。 Camlは、通信技術のアップグレードに合わせてライブラリーの更新をいくつか行うだけで済みます。31

このような予測は正しくもあり間違ってもいました。 アプリケーションの構造は広範囲に進化し、.NETとJVMは最終的に「ミドルウェア」としての役割を強調しなくなりましたが、.NETもJVMも死んでいません。 言語とランタイムはアーキテクチャーよりも長持ちするようです。

さて、2001年中頃には、例のむずがゆさはまだ残っていました。 MSRはどうやって、強く型付けされた関数型プログラミングを多くのプログラマーが簡単に採用できるような形で.NETにもたらそうとしていたのでしょうか? 2001年10月10日までに、筆者は確信を感じながら次のように返答しました。

時間があればCaml用の.NET CLRコンパイラーを実装する予定です。 最初は、私はコア言語、そしておそらく最優先のモジュールだけを実装し、それからその後でいろんなことを評価します。 既存のOCamlコンパイラーのソースを使用するのではなく、ゼロからコーディングして実装しようとおもいます。

これに着手する一番の理由は、私が既存のOCamlコードベースを持っていて、それを.NETライブラリーとして利用可能にしたいと思っているからです…。 加えて私はCamlが大好きなので、それが.NETでサポートされることを望んでいます。 そして、関数型言語間の相互運用性が.NETにおいて実用的であることを証明することにも興味があります。

この実装パスによって、オブジェクトイントロスペクション機能がただで手に入るでしょう。 ですが、間違いなく既存のネイティブコードのCaml実装より遅くなるでしょう。 代償なしで手に入るものはないのです。

Camlの.NETコンパイラーを開発する アクティブな 取り組みについては他にあるかどうか知りません。 SML.NETは近々公開される予定とのことですが、そうであればいいと思います。

そして2001年後半までこの道は継続しました:.NET自身をターゲットにしたOCaml言語の変種を生み出すことです。 OCamlに関連したProject 7の取り組みでは、Leroyによる上記のアプローチが行われるようになっていたのですが、継続する見込みはありませんでした。 これによって、.NET IL自体をターゲットにしているものの、新しいCaml.NETイニシアチブの余地が生まれました。 そして2001年12月に筆者は "Caml.NET" (その後 "F#" にブランド変更されました32)で前進することに決めました。

草創期のF# -- 2002 ~ 2003

F# の初期の概念は単純でした。つまり、OCamlの利点を.NETに、そして.NETの利点をOCamlにもたらすこと: 強く型付けされた関数型プログラミングと.NETの結婚です。 ここで "OCaml" とは、言語そのもののコアと、それが表現する強く型付けされた関数型プログラミングへの実用的なアプローチの両方を意味します。 最初のタスクは比較的明確に定義されていました。 筆者は、OCaml言語のコアとそのベースライブラリーの一部を、.NET Common Language Runtimeをターゲットにするように再実装しました。 実装は新鮮なものでした。すなわち合法であることを明確にするために、OCamlのコードベースを何も使わなかったのです。

F# 実装の最初の行は2001年12月に書かれました。 これは、バックエンドとしてILXをターゲットとしたCamlの主要な構文の再実装のフロントエンドであり、したがって.NETへのフロントエンドでした。 初期のコンパイラーはOCamlを使って書かれました(後に2006年にF# を使ったブートストラップに置き換えられました)。

最初の設計選択は細かいものでした。これまでのところ最も広範囲にわたる設計上の決定は、振り返ったときに簡単に見逃してしまいます。 F# の一番の設計選択は.NET言語になることでした。他のすべてはその目的に従順であることでした。 特に、.NETの型はF# の型で、.NETの値はF# の値で、.NETの例外(およびそのセマンティクス)はF# の例外(およびそのセマンティクス)で、そして.NETのスレッドはF# のスレッドです。 逆も同様で、「双方向の相互運用機能」は常に設計上の目標でした。型変換や、表現間のマーシャリングはありません。 F# の文字列は.NET の文字列となり、その逆も同様です。 F# で定義された型と関数は他の.NET言語からも使用できます。 この決定により、F# はイノベーションの余地が少なくなりました -- F# は多くの場合、.NETのやり方にこだわります -- が、それによって双方向の相互運用が保証されました。 これは、既存の言語を.NETにマッピングするのではなく、新しい言語設計を開始した大きな理由でした。 型やデータを完全に別のものとして扱うことは、ランタイムを1つにするか2つにするかという問題を超えています: ランタイムが1つであっても、ある言語が整数のリスト(たとえば)に独自の表現を使用するという選択もできたでしょう。 そして、内部的にはある種の.NETオブジェクトとして表現されていますが、.NETのメソッドに渡されると整列化されるというように。 ランタイムは1つ、表現は2つというわけです。 F# はそれをしません:F# では1つのランタイムと、可能な限り同一の表現を使います。これは多くの小さな決断に影響を与えました。 例えば、F# で宣言された関数は当初から安定した名前を持つクラスの静的メンバーとして、.NETコードの中で保証され安定した表現を持ち、.NET言語から直接使用できました。 これはまた、F# のコードに常に.NETのリフレクションを介してアクセスできることを意味しました。 F# の最初のバージョンは当初 "Caml for .NET" と表現されていましたが、実際には新しい言語が常に使用されていました。 最初から.NET用に設計されているけれども、Camlを設計ガイダンスとインスピレーションの主な源としている言語です。

さらに、何を実装しないのかという問題もありました。 設計時点での著しい省略はOCamlの関手的モジュールシステムでした。 ファンクターはStandard MLの重要な部分であり、OCamlにはこの機能の修正版が含まれていました。そのことは、理論家の間でいまだに進行中の、論争の源です。 筆者はプログラミング言語でパラメーター化が可能となる「ゴールドスタンダード」としてのファンクターに積極的に対処しましたが、ファンクターの理論上の複雑さには用心深くしていました。 さらに、当時、実践的なOCamlプログラマーによってファンクターが使用される場所は比較的少なかったのです。 OCamlモジュールシステムの一部 -- ネストされたモジュール定義 -- はF#の設計に最終的に含まれました。 しかし、ファンクターは.NET上で直接実装するのが難しいと認識されており、.NETオブジェクトプログラミングと両立する形で言語設計に含めることを正当化するのは困難でした。 もう1つの決定は、OCaml 3.0の機能、特に、オブジェクトシステムや最近追加された「名前付き引数」機能を含まないことでした。 上のLeroyのEメールはオブジェクトシステムに関する問題を説明しています: .NETとOCamlのオブジェクトシステムの間には十分な差と不一致があり、後者は前者から使用できませんでした。 CamlLexおよびCamlYaccを使用することはできましたが、OCamlプリプロセッサーのCamlP4もサポートされていませんでした。オブジェクトシステムの問題については後で説明します。 しかし、これはF#とOCamlがOCaml 2.0のコア言語を起点に分岐したことを意味します。

最初のリリース(v0.1でしたが、すぐに0.5で置き換えられました)はILXプロジェクトへの追加として2002年6月4日に限りなくひっそりと行われ33 、Webサイト上で次のような主張をしました。

関数型と命令型の混合プログラミングは、多くのプログラミングタスクにとって素晴らしいパラダイムです…。 F# を使用して、何百もの.NETライブラリーにアクセスできます…。 F# は、.NET Framework用のCamlプログラミング言語のコアと、言語間の拡張機能の実装です。 …目的は、C# 、Visual Basic、SML.NET、その他の.NETプログラミング言語とシームレスに連携することです。 …MLプログラムの型と値は、予測可能かつわかりやすい方法でいくつかの重要な言語(C# など)からアクセスできます。 …F# は、OCamlライブラリーのサブセットの実装と.NETライブラリーにアクセスする機能を提供します。.NETライブラリーの使用はオプションです…。 F# は、Unicode文字列や動的リンクなど、MLの実装に欠けていることが多い機能をサポートしています。 …ツールは単純なコマンドラインコンパイラーで構成されていて、分割コンパイル、デバッグ情報、および最適化をサポートしています…。 F# は、私の知る限りでは、優れたバイナリー互換性とバージョン管理特性を持つ最初のMLコンパイラーです。

途中、いくつかのハードルが取り除かれました。 MSRはILXでコンパイルされたプログラムの商業利用を認める許可を与えました、そしてこの許可はF# 実装のためにリサイクルされました。 次に、ある会議で、筆者はLeroyに対し、言語設計の変更を含んだ、.NET用のCaml変種を発表することにおける暗黙の承認を求めました。 Leroyは承認しました -- OCaml自体、MLのコアを適応させ修正する長い歴史の一部でした -- そして私たちが実験しなかった場合、研究はどうなったでしょうか? 後のEメール返信で、Leroyは次のように述べました。

Don SymeとMicrosoft Cambridgeにいる彼の同僚は、.NET Frameworkにパラメトリック多相 -- 当初.NETで見過ごされていたもの -- を追加する素晴らしい仕事をしました。 そして彼らがこの拡張を実際に動かして見せるためにCamlのコアを選んだことをとても嬉しく思います。 https://caml.inria.fr/pub/ml-archives/caml-list/2002/06/8d07fd5058aa26127d1b7e7892698386.en.html

それに対する私の返事:

そして私は、Xavierとチームにさらに感謝しています。 OCamlを使ったこのような素晴らしい仕事を何年にもわたってしてくれたこと、 そしてしっかりしたコア言語や、優れたランタイムシステムや、コアに追加した非常に興味深い一連の言語機能を提供してくれたことに対して。 コアCamlはあらゆる種類の仕事のための素晴らしい出発点を提供します: 私は私の博士論文で、例えば定理証明のための用語言語としてそれを使いました。

私が.NET用のコアCamlコンパイラーを実装することにしたのは、部分的にはジェネリックをテストするためです。 しかし、それは私がプログラミングしたい言語を使用して.NETライブラリーに対してプログラミングできるようにしたいからでもありました。 私は自分が開発したライブラリーとテクニックを再利用したいと思います。 F# について、もしかしたらCamlコミュニティから少々の不満があるかもしれません。 私はMicrosoft Researchにいるので、遅かれ早かれかなりの.NETコードを書くことになると思います。 個人的には、C# よりもCaml/F# でそうしたいと思います。 …F# の一般公開を通して私がその機会を他の人にも利用可能にしたとしてもCamlコミュニティが気にしないことを願っています。34

最初の実際的な設計作業は、ドット表記法を介して.NETオブジェクト型にアクセスする機能の追加から始まりました。

C# や他の.NET言語はF# から直接アクセスできます…。 型は Namespace.Type 表記を使ってアクセスします。 open Namespace 宣言が与えられている場合は、単に Type を使用することができます。 インスタンスメンバーは、 obj.Method(arg1, ..., argN)obj.Property 、または obj.Field を使用してアクセスされます。 静的メンバーは、プロパティやフィールドと同様に、 Namespace.Type.Method(arg1,...,argN) または Type.Method(arg1,...,argN) を使用してアクセスされます。35

一見無害に思えますが、この設計判断はOCamlとML言語設計の長い伝統とを破りました: この設計は名前解決において推論された型情報を使います。 obj.MMのような名前は、新しい推論制約を追加するのではなく、objの部分推論型を使用して解決されることになりました。 つまり、型注釈が必要になることがあり、MLの伝統的な「規則」の1つ(つまり、型注釈は完全にオプションである)が損なわれ、その推論は「アルゴリズム的」すなわち「左から右」になります。

型付けについて。プログラムに型チェックをさせるために余分な注釈が必要になることがあります。 たとえば、 (cast <expr>:<type>) を使ったキャストや、型注釈を使用したオーバーロード解決などです。

これは非単調性の可能性を生み出すことにもなり、その場合は新しい推論情報を追加すると名前解決が変わってしまうかもしれませんでした。 筆者は、推論アルゴリズムが明確に定義され安定していて、非単調な解決が起こらなければ、相互運用性の目的にはこれで十分であると判断しました。 結果的には、名前解決における部分的に推測された型情報の使用は効果的で安定していることが証明され、F# の進化の間中ずっと維持されていました。 最終的に、型推論は言語仕様でアルゴリズム的に定義されました。

もう1つの設計上の課題は、Nullについてでした。 SML.NETシステムでは、関連するすべての箇所に、標準MLが備えるSOME/NONEタグ付きの "option" 型を挿入することによって、すべての相互呼び出しを「サニタイズ」していました。 筆者は、F# ではそうしないことに決めました:

Nullについて。.NETアセンブリによって返されたNullオブジェクトは、アセンブリのインポートプロセスやF# 型システムによってチェック されません 。 この問題は将来解決される可能性がありますが、 しばらくの間は、Pervasivesの "nonnull" 関数を使用して値がnullかどうかをチェックしたり、Objの "null" 値を使用して新しいNull値を作成したりしてください。 Internet Archive: http://research.microsoft.com/projects/ilx/fsharp-manual-import-interop.htm

これは、人間工学による判断でもあります。 プログラミングするにあたりオプション型の挿入は非常に煩わしく、.NETのライブラリーではJavaのライブラリーほどNullが広く使われていないため、 バランスを考慮すると、プログラミング体験を快適にする必要性が相互運用におけるNull安全性の必要性を上回りました。 さらに筆者は、Null安全性の問題は.NET Genericsで行ったようにすべての.NET言語にまたがって体系的に扱われるべきであると感じました。36

当初、初期のF# ではオブジェクトプログラミングの宣言を追加することを避けました:

現在のところ、F# の中で新しいクラスを宣言することもインターフェースを実装することもできません。 当面の回避策は、仮想メンバーまたはインターフェースメンバーを実装するデリゲートパラメーターを受け取る新しいクラスをC# で宣言し、 そのC# クラスにF# から関数値を渡すことです。 このC# クラスは、一度だけ書く必要があります。

さらに、前に示したEメールスレッドの中にあったDave Berryらによる警告に反して、スレッド処理には設計作業は必要ありませんでした。 F# は単純に.NET自体と同じスレッドモデルを想定していました。これは本質的に.NETの複数スレッドをOSの複数スレッドにマッピングしたものです。

草創期のF# -- リリース

F# "0.5" は、最初はほとんど気付かれていませんでしたが、それは意図的でした:初期実装は多くのものが欠けており、解決するのに時間がかかったからです。 当初の計画は次のとおりです。

  1. 当該言語を採用して使用できるようにする。
  2. .NET Genericsのストレステストに使用する。
  3. 一般公開する。
  4. 成り行きを見守る。

筆者は、Intel Strategic CAD Laboratoriesで過ごした時間に影響されていました。 そこでは研究プロジェクトと技術開発において、構造化された「成熟度モデル」が使われていました: Intelのプロジェクトは、「コンセプト」から「コンセプトの証明」、「プロトタイプ」、そして製品納入という段階を経て進められるものでした。 そのため、現段階ではMicrosoftの「賛同」はありませんでした: 社内でもF# を知っている人はMSR Cambridgeのメンバーおよび彼らと交流のある.NETチームのメンバーを除いてほとんどいませんでした。 6か月後、何度かのイテレーションの後、このプロジェクトは常に最新のスクープを待ち望んでいるインターネットのニュースサイトに取り上げられました。 そして、物事が「手に負えなくなった」場合、および「取り込み、拡張し、抹殺する」の告発が出た場合に備えて、 筆者は実装が完全に準備される前にOCamlメーリングリストで名言することにしました。

ここ数日の間に、このプロジェクトについて完全に推測を元にした(そしてすっかり的外れな!!)インターネットの報道がいくつかありました(例えばinternetnews.comを参照)…。 F# のWebサイトに次の説明を追加してこのリストに投稿するのが賢明だと思いました。

…違うことを示唆するような報道はありましたが、 F# は.NET Frameworkで使えるMLのような言語を簡単に実装することが可能であることを実証するために設計された、比較的小さな研究プロジェクトです。 F# を商品化する計画は現在ありません…。 F# は一般公開されている、現在進行中の研究であり、Microsoft Researchはいくつかのプログラミング言語に関して複数の大学と定期的かつオープンに共同研究を行っています。37

当初F# を小さく見せる必要があったという事実は、当時MSRから「製品に似た」ものをローンチすることに対する敏感さのせいでもありました。 当時、MSRによるすべての公開ソフトウェアは法的/商業的に厄介なステータスを持っていました: ソフトウェアの公開は主に研究/公開アジェンダをサポートするためでした。 予算が1Bドルに近づいたにもかかわらず、MSRはその段階では商業製品の作成とリリースを許可されていませんでした。 MSRはオープンリサーチを強く推奨しましたが、オープンソフトウェアはもっと問題がありました。 しかし、新しいプログラミング言語を設計し、 そして提供する ことは、あらゆるプログラミング言語研究アジェンダの重要な部分であり、 実際、Project 7の背後にある根本的理由のすべてでもあります。 さらに、これらの技術を外部で「実証」することは、それらを洗練するために重要でした。

外部からの認識もまた扱いにくいものでした: コンピューターサイエンス学術界およびハッカー文化の観点から見ると、企業全般 -- 特にMicrosoft -- は、構造的な逆境と見なされることがよくありました。 MSRからの申し出はさらに恐れられていました、そして、ある主要な研究者はF# が言語研究を「殺す」だろう、と示唆しました。 振り返ってみると、そのような発想は笑えます -- プログラミング言語研究はここ15年の間も花盛りで、何百もの新しい言語が開発されてきたからです -- 。 しかしこれらの見解は、反商業主義の偏見、独占主義者と認識されている存在に対する恐れ、および当時のオープンソースソフトウェアに対するMicrosoftの敵対から生じたものです。

いずれにせよ、物事を変えるチャンスがあり、研究の精神とProject 7の当初の目標の両方に忠実であるならば、一般公開され、商業的に利用可能でなければなりませんでした。 後に、MSRの他の先端プロジェクトが潜在能力を完全には発揮できないことがありました。 なぜならそれらは、技術を実証して有用性の証拠を得るために必要なはずの商業利用可能なリリースを、市場のニッチを占めるのに間に合う時間内に作成しなかったからです。 例としては、AcceleratorおよびDryad LINQがあります。 その一方で、専門知識の集中や、コンピューティングを変革するという長期的な使命を考えると、MSRは言語にとって優れた「制度上の家」を提供したといえます。 Andrew Herbert、Luca Cardelli、Andrew Blakeなどのラボディレクターは、長期間にわたってF# の作業を一貫して支援してくれたものでした。 しかし、一般公開され商業的に使用可能な言語の提供をMSRが行うことは簡単なこととは言えず、最終的には製品チームのサポートが必要になるものでした。

F# 1.0 -- 2004 ~ 2006 -- 概要

.NET Genericsを2004年半ばに完成させた後、その年の残りの時期にはF# の改善に関して筆者による集中した作業が見られました。 その時点では、.NETはMicrosoftの中で非常に重要な位置を占めていましたし、布教のための莫大な努力のおかげで広範囲に及ぶ社外での成功を達成しました: Windowsプラットフォーム用のほとんどのプログラミングは、世界中でC# と.NETに移行しました。 社内的にも.NETへの大きな移行が起こりました。 Windowsチームは、Windowsの「シェル」の書き換えや、 Windows Presentation Foundation、Windows Communication Foundation、Windows Workflow Foundationなどの多数の主要な.NETプロジェクトの作成など、 大きなイニシアチブを開始しました。

2005年1月5日に、筆者の最初のMSDN(Microsoft Developer Network)ブログエントリーでF# 1.0のプレリリースが宣言されました38。 2005年3月、レドモンド(訳注:米国本社)で開催されたMSRの内部見本市である "TechFest" で、F# 1.0が初めてデモされました。

Figure 2 -- MSR TechFest 2005でのF# 1.0のポスター2枚

F# は2004年から2006年までの開発できわめて重要な動きがありました。 トライアルの成功に基づき、そしてByron Cookの支援を得て、MSRマネージャーのLuca Cardelliはプロジェクトに開発者支援を追加することに同意しました。 2005年2月10日には広告を出すことができ、 2005年3月24日にJames Margetsonが加わって、インターンと一緒に小さなチームを結成しました(Dominic Cooney、2004年5月~7月、Gregory Neverov、2006年6月~8月)。 社内外の小規模なユーザーコミュニティが成長し、プロジェクトへの信頼が形成され始めました。 この時期にF# に行われた技術的な追加は次のとおりです。

  1. Camlに似たコア言語プログラミングモデルの完成(2004)
  2. .NETジェネリックをターゲットにする(2004)
  3. 初期化グラフの追加(2004)
  4. .NETとの相互運用性のためのドット表記法、メソッドオーバーロードの解決、およびオブジェクト式の追加(2005)
  5. オーバーロードされた演算をHindley-Milner型推論に適合する方法で処理するための「静的に解決された型パラメーター」の追加(2005)
  6. オブジェクトプログラミングのためのクラス/インターフェース構築の追加(2005)
  7. 暗黙のクラス構築の追加(2006)
  8. 字下げを認識する「軽い」構文(2006)の追加
  9. Hindley-Milner型推論におけるサブタイピングの扱いの追加(2006)
  10. クォートによる実行時メタプログラミングの追加(2006)
  11. F# のREPLであるF# Interactiveの追加(2006)
  12. 初期のVisual Studioツール(2006)
  13. ブートストラップ化(2006)
  14. Monoを使ったLinux上での実行(2006)

この言語を「実証」するために、SPiM(Stochastic Pi Machine)、Static Driver Verifier、およびTerminatorプロジェクトを含む、MSRの既存のOCamlコードベースに目を向けました。 これらのテストは成功しました。たとえば、SPiMにWindowsベースのGUIを追加することができました。 その時期に、James Margetsonは、Andrew Phillips、Jakob Lichtenberg、Byron CookによるこれらのプロジェクトでのパフォーマンステストとF# の内部使用のサポートを担当しました。 Margetsonはまた、F# 用の最初のREPLを実装し、F# スクリプティングとREPLを使用したインタラクティブ開発の説得力のあるデモを数多く作成しました。 筆者とMargetsonはドキュメンテーションとリリースに責任がありました。

この時期のF#の成果はMSR Cambridgeの言語研究者たちとの「合意」の結果ではなく、むしろ最初の実装に一連の設計を追加することを追求していた筆者と共同研究者たちの結果でした。 そしてそれは、同僚、ユーザー、WG2.8(訳注:情報処理国際連合IFIPの関数型プログラミングワーキンググループ)などの研究者ネットワーク、そして世界的に出現しつつあるコミュニティからのフィードバックの助けを借りていました。 メーリングリストやブログの回答で行われた、外部コミュニティでの設計上の会話は励みになり、社内外の採用は着実に増えていました。

F# 1.0 -- パイプライン

最初にF# に関連付けられるものは、最も単純なものでもあります。2003年にF# 標準ライブラリーに追加された「前方パイプライン」演算子です。

let (|>) x f = f x

カリー化された関数の適用とともに使えば、連鎖する関数の中に中間結果を通過させることができます。例えば:

[ 1 .. 10 ]
    |> List.map (fun x -> x *x)
    |> List.filter (fun x -> x % 2 = 0)

と書けるので、次のように書かなくてよくなります。

List.filter (fun x -> x % 2 = 0)
    (List.map (fun x -> x *x) [ 1 .. 10 ])

F# が連想されることが多いのですが、ML方言でのパイプライン記号の使用は、1994年5月にTobias Nipkowによって開始されました39

…私(訳注:Marius Wenzel)は古いメールフォルダを掘り下げて、|>にまつわる本当の語を明らかにすることを約束しました。 それはIsabelle/MLで生まれたのですが、F# でも人気がでました… (Scalaの例ですが、http://paste.pocoo.org/show/134013/ を参照してください。そこでは、「F# のパイプライン演算子」と引用されています)。

添付ファイルは、1994年4月から5月にかけての私たち3人 [Larry Paulson; Tobias Nipkow; Makarius Wenzel] のオリジナルのメールスレッドです。 今やML界隈の欠くことのできない部分となったそれを考えついたのはそこです。メール交換は、私の変更に対するLarryの返信として始まります。40

…最後に|>という実際の名前を思いついたのは…Tobiasでした…

F# ではパイプライン記号の使用が特に重要です。型推論が左から右に伝播され、名前解決はプログラムの前方で使用可能な情報に基づいて行われるためです。 たとえば、次の例では、明示的な型注釈なしで型チェックに合格します。

let data = [ "one"; "three" ]
data |> List.map (fun s -> s.Length)

対照的に、次のコードは明示的な型注釈を必要とします。

List.map (fun (s: string) -> s.Length) data

とはいえ、F# よりも前から、筆者や他の人々によってパイプラインは多用されていました。 F# ライブラリーでは2引数と3引数のパイプライン演算子も定義しました。例を示します。

let (||>) (x1, x2) f = f x1 x2
(0, data)
    ||> List.fold (fun count s -> count + data.Length)

F# 1.0 -- オブジェクトプログラミングへの取り組み

当初から、F# は.NETのクラスとインターフェースの定義を利用できました。 関数型言語なので、関数クロージャーと同じような式ベースの形式のオブジェクト実装をサポートすることから始めるのが自然でした。 F# 1.0では、これらについて次のように説明しています。41

オブジェクト式は、クラスまたはインターフェースの実装や拡張を宣言します。 たとえば、以下はF# に組み込まれた 多相 < および > 演算子の機能を使用して、.NETのIComparerインターフェースを実装するオブジェクトを構築します。

{new IComparer with Compare(a,b) = compare a b }

OCamlのようなレコード型を使用して.NETのクラスを宣言するよう試みた後で、 筆者は2005年4月27日に、Dominic Cooney宛ての電子メールを通じて、F# のオブジェクトプログラミング拡張機能の設計プロセスを開始しました (彼はもうインターンではありませんでしたが、個人的な議論のためにF# とサウンディングボードを使用した経験がありました)。

F# のAPIをもっとOO的な方法で公開できるようにするというニーズに絶えず直面しています。 …言語メカニズムとAPI自体の両方のドラフトをあなたにお渡しして、コメントをもらえないかと思うのですが。 F# のライブラリーと、.NETライブラリーに期待される標準の両方にとても精通していますから。

この議論の次回のやり取りは2005年5月19日になされましたが、 その時にF# のオブジェクトプログラミング用構文はほぼ最終的な形をとりました(後から追加した、暗黙的なコンストラクターを除きます)。

type X =
  override x.ToString() = "abc"
  member x.InstanceProperty = "fooproperty"
  member x.MutableInstanceProperty
    with get() = "fooproperty"
    and set(v) = System.Console.WriteLine("mutated!")

  member x.InstanceIndexer
    with get(v) = v+1

  member StaticProperty = "fooproperty"
  member MutableStaticProperty
    with get() = "fooproperty"
    and set(v) = System.Console.WriteLine("mutated!")

  member x.InstanceMethod(s1) = "baz"
  static member StaticMethod(s1,s2) = "static method"

この構文では、 "x" は "this" または "self" パラメーターの名前です。 このパラメーターにユーザー定義の明示的な名前を使用するという決定は、部分的にはOCamlシステムで同様の決定がなされたことに影響されましたが、 別の部分では、Javaの内部クラスにおける "this" の解決がややこしいという学術論文を査読していた時に筆者が経験した「おぞましさ」の感覚によるものでした。 そのような構成要素がネストすることは結局必要となりますし、そしてML族の言語では普通と考えられるので、明示的な名前を要求するほうが良いでしょう。

振り返ってみると、F# に対するオブジェクトプログラミングの追加は、 オブジェクト指向をその本質的な要素(約20の個別機能:ドット表記、クラス、メソッドオーバーロードなど)に「分解」し、それらの一部をF# に変換して組み込むプロセスでした。 その際には、コアである式言語の本質を維持し、継承よりも委譲を強調した方法を取りました。 筆者は最近では、「F# は『オブジェクト』プログラミングを包含しますが、『オブジェクト指向』プログラミング、特に実装の継承には重点を置かないようにしています」と要約しています42。 たとえば、 "protected" アクセシビリティ修飾子は、実装の継承を促進すると考えられているため、今日でもF# ではサポートされていません。

F# 1.0 -- 機能コアの改善:初期化グラフ

F# に追加された最初の奇抜な機能は、強く型付けされた関数型言語でこれまで使用されていなかった類の、初期化と再帰の調整でした。 これは、最初は2004年半ばに設計・実装され、2004年9月4日にMSR Cambridgeで、その後ML Workshop 2005で発表されました(Syme、2006)。 この機能は、Georges Gonthierとの廊下での会話、および可能な限り再帰的定義に「共帰納的」解釈を与えるというアイディアに触発されたものでした。 共帰納的手法 -- オブジェクト指向の解釈としての共帰納的代数を含む -- は、当時の人気のある研究トピックでした。 2004年のプレゼンテーションでは、筆者は「リアクティブオブジェクト」のネットワークを定義する方法に焦点を当てました。

サブタイピングを忘れましょう。継承を忘れましょう。 自己参照および相互参照オブジェクトに対する制限は、MLをGUIプログラミング言語としては不便なものにしています…。 少なくとも System.Windows.Forms のような妥当なライブラリーを駆動する場合に不便ですし、そしてライブラリーが「宣言的」になるほど悪化します…。 C# は、暗黙のNullや「作成してから構成する」APIを使ってこれを「解決」します。MLでも同じように「解決」します。 Haskellでは注釈を多用してAPIを再設計するしか方法がほぼありません。 F# はこれらの手法を許可しますが、別の解決策も提供します…(Syme、2004)

提供した解決策は、 "let rec" 構成体を拡張し、関数だけでなく、値とオブジェクトのグラフ構造も定義できるようにすることでした。 たとえば次のように、です。

F# を使用すると、自分自身を参照しているような仕様に見えるけれども、自己参照は遅延された値の中に隠れているような値(関数だけでなく)を書くことができます。 それは、内部関数、その他の再帰関数、匿名の "fun" ラムダ、遅延計算、そしてオブジェクト実装式の「メソッド」などです。

その再帰は「実行時にチェック」されます。これは、バインディングの評価に伴う計算が、実際には遅延計算を取り込んでおり、それらを実行する可能性があるためです。 実行時の自己参照が発生した場合に例外が発生するように、F# コンパイラーは遅延とサンクを挿入します。

その再帰は「リアクティブ」です。これは、さまざまな入力に応答し、結果として自己を参照した変更を行うオートマトン、 たとえばフォームやコントロールやサービスなどを定義するときにのみ使うことだけが本当に意味があるためです。 簡単な例として、メニュー項目を次に示します。これは、アクションの一部として状態の一部を出力します。

let rec menuItem =
    new MenuItem("Say Hello",
                 EventHandler(fun e -> printf "Hello %s\n" menuItem.Text),
                 Shortcut.CtrlH)

これにはコンパイラーが警告を表示します。 理論上は、 "new MenuItem" コンストラクターが構築プロセスの一環としてコールバックを評価する可能性があり、 その場合は自己参照が発生することになるからです -- そしてF# はこれが起こらないことを証明できません。

ML Workshopの論文は、この機能の歴史的な先例を紹介しています。 これは現在のF# でも時折使用されており、F# オブジェクトプログラミングの設計のいくつかの面に影響を与えました: F# 2.0のクラス定義では、オブジェクトの構築中にサブクラスのオブジェクトメンバーを「再帰的に」呼び出す仮想呼び出しは初期化の安全性がチェックされ、 初期化が完了する前に再入が起こると例外が発生します。

F# 1.0 -- 機能コアの改善:オーバーロードされた演算

OCamlの明白な問題の中にはオーバーロードされた演算の問題がありました。 OCamlはHaskellのスタイルで型クラスを追加することを避け、代わりに整数や浮動小数点数の演算に対し、語句の構成的にあいまいな(訳注:syntax-ambiguated)アプローチを採用しました。

let x1 = 1 + 1 (* an integer*)
let x2 = 1.0 +. 2.0 (* a floating point number *)

このアプローチはシンボリックプログラミングには実用的でした。数値型を広く使用しないからです。 ですが、この分野に独自の基準を持つ.NETのコンテキストでは実用的ではありませんでした。 例えば、オーバーロードされた算術をサポートする型は、静的メンバー呼び出し op_Addition などをサポートすることによってこれを示します。 この問題を解決するためのF# アプローチは、HM(X)とG'Caml(OCamlでこれらの問題を扱うための提案)に関する研究に触発されました43。 特に、「メソッド制約」が追加されました。これには、意図的に奇妙な形式の構文を導入しました。

let inline (+) (x: ^T) (y: ^U) : ^V =
 ((^T or ^U): (static member op_Addition : ^T * ^U -> ^V) (x, y))

この定義によれば、+の使用はすべて、適切に型指定された op_Addition メソッドへの呼び出しをインライン化することによって実装されます。 型変数の ^T 表記は、静的に解決される型パラメーター(SRTP)を示します。 この構文をサポートするためだけに inline キーワードがF# に追加されました: インライン化することにより、使用時に利用可能な型に従って制約が解決されます。 これにより、オーバーロードされた算術演算をHindley-Milner型推論ときちんと統合し、コードをより自然な形にすることができます。

let x1 = 1 + 1 // an integer
let x2 = 1.0 + 2.0 // a floating point number
let x2 = DateTime.Now + TimeSpan.Years(1.0) // a date

SRTPはその後、制約されたジェネリクスのメカニズムとして、F# でさらに一般的に使用されるようになりましたが、 元々はオーバーロードされた算術演算に対処するために特別に設計されたものです。

F# 1.0 -- 機能コアの改善:アクティブパターン

1980年代から、強く型付けされた関数型プログラミング言語の最も人気のある機能の1つはパターンマッチングであり続けました。 F# とOCamlでは match ... with ... 構成体で表されています。 Wadlerによるビューの研究(Wadler、1987)以来、パターンマッチングには抽象化に欠ける問題があることが認識されていました: 既存のデータ型または抽象データ型に対して新しいパターンマッチング構成体を書くことはできません。 2005年のF# の「実証」の間に、SPiMやStatic Driver Verifierのような実世界のOCamlコードベースにおけるこの問題の重要性が、筆者には明らかになりました: これらのコードベースでは、型の実装の詳細がパターンマッチングによってコードに「漏れて」いるため、コア表現の変更が困難になっているケースが多数ありました。 2006年初めに、筆者はこれについてF# では何をすべきかを決定するプロセスを開始しました。

「アクティブパターン」や「ビュー」という考え方は学界では取り上げられていましたが、 強く型付けされた関数型プログラミングの実用システムでは実装されたことはありませんでした(Erwig、1996)。 F# は、表現が非公開である.NETオブジェクト型と相互運用する必要があったため、拡張可能なパターンマッチングを追加するのが自然になりました。 2006年5月、Gregory Neverovがプロジェクトにインターンとして参加し、このトピックに割り当てられました。 プロトタイプがすぐに登場し、7月16~21日にボストンのWG 2.8で発表されました44。 参加者の一人にMartin Oderskyがいて、2006年7月25日に彼から返信をもらいました。

WG 2.8であなたと議論したのはとても楽しかったです。 その後、私はScalaでアクティブパターンをどう扱うか考えてきました。 実在型を依存型で置き換えることができるようです。 現在のところ、GADTのような振る舞いをさせる方法はまだ明確ではありません。

このEメールと最初のEPFL論文(Emir, Odersky, & Williams、2007)から見ると、F# にアクティブパターンを追加したことはScalaの設計に何らかの影響を与えたようです。 F# (アクティブパターン)とScala(抽出子)のそれぞれのメカニズムの最終バージョンは、ほぼ同時に設計され実装されました。 Simon Peyton Jonesは当時F# について非常に役立つアドバイスをしました。 Haskellにビューパターンを追加しようとするさまざまな試みについて筆者に説明してくれたのです。 その中で、そのような機能を追加するにあたり、「努力に見合うだけの価値があるので」やらなければいけないことについて強調していました。すなわち宣言と使用の簡単さです。 F# アクティブパターンの初期実装は2006年8月にリリースされ、その後にICFPの論文が続き(Syme, Neverov, & Margetson、2007)、 それからずっと、この機能はF# 言語の中で非常に広く使われている部分です45

F# 1.0 -- 機能コアの改善:ファーストクラスのイベント

初期のF# アプリケーションにはSPiMのようなシステム用のGUIプログラミングが含まれており、 必然的にF# は以前のMLファミリーの言語設計と比べて、リアクティブ、非同期、およびイベントベースのプログラミングに重点を置いていました。 .NETメタデータとC# には、「イベント」という組み込みの概念が含まれていましたが、ファーストクラスではありませんでした: イベントをファーストクラスの値として扱うことはできませんでした。 F# オブジェクトシステムを設計する過程で -- そしてそれを単純化して正規化するために -- 、 「ファーストクラスのイベント」はF# 言語とライブラリーの拡張として設計され、2006年3月23日にリリースされました46。 ファーストクラスのイベントの代表的なコードサンプルは次のようなものでした。

let mouseMove =
  form.MouseMove
  |> Event.filter (fun e -> e.Button = MouseButtons.Left)
  |> Event.filter (fun _ -> inputMenuItem.Checked)

ここで form.MouseMove はハンドラーの登録と解除を可能にするファーストクラスのイベントです。 イベントの合成は、form.MouseMove のトリガーをフィルタリングして、 マウスの左ボタンが押されて特定のメニュー項目がチェックされたときにのみ発生する新しいイベントを生成します。 こうして、イベントの合成、フィルタリング、組み合わせ、および変換という一般的なパターンを抽象化できるようになりました。 この機能の追加はWes Dyerに直接影響を与え、Erik MeijerによるReactive Extensions(Rx)プロジェクトの開始にもつながりました47。 イベントハンドラーを登録するとメモリーリークが発生することが予想されますが、 後に、F# プログラミングモデルのこの部分をRxのIObservable型を使用するように変換することで対処されました、 このトピックはまた、PetricekとSymeによる、リアクティブシステムにおけるガベージコレクションをテーマにしたF# 関連の出版物にもつながりました(Petricek & Syme、2010)。

F# 1.0 -- 機能コアの改善:コンピュテーション式と非同期

2007年4月に、筆者はMartin Oderskyと共にローザンヌのEPFLで6週間のサバティカルを過ごしました。 OderskyはScalaを開発していましたから、言語とグループのための刺激的な時間だったわけです。 その時の訪問の中で、もう1つの重要なアイディアが種をまかれ、最終的にはコアF# 設計に追加されることになりました。 それは、コンピュテーション式 およびその 非同期プログラミング への応用です。 それは数年後のC# に影響を及ぼし、C# 5.0(async/await)および8.0(非同期シーケンス)になり、さらに他の多くの言語にも影響を及ぼすことになりました。

コンピュテーション式と "async" で解決した問題は以下の通りです。 まず、2003年以降、コモディティであるコンピューティングシステムにおけるマルチコアおよび並列処理への注目が高まっていました。 そして、Webプログラミングの台頭により、サーバー側での同時実行性と、クライアント側で長時間実行されるWeb要求が重要視されるようになっていました。 さらに、Windowsのコンテキストでは、「OSのスレッドは高価である」とみなせたため、純粋にOSのスレッドに基づく並行性へのアプローチは除外されました。 このような要因の組み合わせにより、言語とフレームワークは並行性とユーザーレベルスレッドについて強い視点を持つようになりました。 .NETでは、当時のC# の仕事の焦点は共有メモリーのプリミティブとロックでした(Duffy & Sutter、2008)。 それらは低レベルで高性能なプリミティブには向いていましたが、.NETコミュニティはより良く、より生産的な抽象化を熱望していました。 他の多くの言語では、アクターのようなメッセージキューイングシステムや、先物(Future)や、継続に焦点が置かれていました。

理論的な側面からは、昔からこのように認識されていました:

  1. 非同期とは、継続渡しを介して実装されたモナディックプログラミングの一種です。
  2. モナディック計算に「構文糖」を追加すると、プログラミング言語または仕様言語に表現力豊かな追加が行われるでしょう。

2007年のEPFLで、筆者はOderskyがScalaでメッセージ処理のための react {…} 構成体を実験していることに気付き、 非同期プログラミングを扱うためのある種の原始的な構成体がF# で必要になるだろうと気づきました。 C# は、C# 2.0に「イテレーター」を追加しました(これもMSRによって開始されたものです)。 これは、非同期プログラミングの文脈で興味深い、制御フローの暗黙の反転を特徴としていました。

非同期プログラミングに関するアイディアは、特にFabrice le FessantによるシステムであるMLDonkey48で使用されている非同期実装を通じて、 OCamlコミュニティとそのメーリングリストにも広がっていました。 Haskellはモナディックシンタックス49、そして後にアローシンタックス50を追加しました。 多くの定理証明システムには、記法の一般的な拡張がありました。 しかし、正格な関数型言語には、すべての制御構造を非同期形式で再解釈することを可能にする適切なモナド構文を備えたものがなく、 OCamlおよびStandard MLでは、関数コンビネーターのライブラリーが代わりに使用されました。

EPFLから戻った後、筆者は2007年5月頃にMargetsonとこれらの問題について議論しました。 彼は非同期プログラミングの実装におけるモナドの重要性を強調しました。 これにより、筆者はついにF# にモナド構文を追加して非同期プログラミングに適用することを試みることとなりました。 そしてそれは、2007年にF#に 「コンピュテーション式」と async {...}を追加することにつながりました。 2007年10月10日に、私たちはこれらの機能をブログ記事「F# の非同期ワークフロー51で発表しました。 当時のブログ記事で使用されていた、非同期コードの代表的なサンプルは次のとおりです。

let task1 = async { return 10+10 }
let task2 = async { return 20+20 }
Async.Run (Async.Parallel [ task1; task2 ])

ここでは:

  • async { return 10+10 }Async<int> 型のオブジェクトを生成します。こういう値は実際の結果ではなく、実行するタスクの仕様です。
  • Async.Parallel [ task1; task2 ] は2つのタスク仕様を合成し、Async<int[]> 型の新しい値を生成します。
  • Async.Run はこれを受け取って実行し、配列 [20; 40] を返します。

識別子 async はコンピュテーション式のビルダーを表します。次のようなコードは:

async {
    let! x = p1
    let! y = p2
    return x + y
}

以下のように解釈されます。

async.Bind(p1, (fun x1 ->
    async.Bind(p2, (fun x2 ->
        async.Return(x1 + x2))))

コンピュテーション式には、F# 言語のすべての制御構造、たとえばtry/finallyや、if/then/elseや、ループなどを含めることができ、 それぞれがビルダーによって構造化された合成可能な方法で再解釈され、ビルダー内のメソッド呼び出しとして脱糖されます。 async.Bindや、async.TryFinallyというような形にです。

驚いたことに、コンピュテーション式に使用された構文機構は、リスト内包表記のような「モノイド」計算を含む、あらゆる範囲の合成可能な制御構造に再利用することができました。たとえば:

[ yield "zero"
  for a in 1 .. 5 do
      match a with
      | 3 -> yield "hello"; yield "world"
      | _ -> yield a.ToString() ]

これは次のように評価されます。

[ "zero"; "1"; "2"; "hello"; "world"; "4"; "5"]

F# へのコンピュテーション式の導入は、1つのハンマーで3つの釘を打ちました: (C# の)イテレーター、リスト内包表記、および非同期プログラミングはすべて、1つの共通的な構文メカニズムを介して処理されました。 コンピュテーション式を利用することができる制御構造のさまざまな系列は、最終的にPetricekとSymeによって特徴付けられ(Petricek & Syme、2014)、 2010年に彼らはJoinadと呼ばれるパターンマッチングの実験的なモナド的一般化を開発しました (Petricek & Syme、Joinads:リアクティブプログラミング、並列プログラミング、および並行プログラミングのための再ターゲット化可能な制御フロー構造、2011)。

F# 1.0 -- メタプログラミング

F# 1.0では、F# に「クォートメタプログラミング」が追加されました。 クォートはLISPの開始以来LISPの重要な機能であり続けていたもので、それ以来さまざまな言語に含めることが可能になっていました。 しかし、強く型付けされた関数型言語やオブジェクト指向言語へ進出することはめったにありませんでした。

2005年に、C# チームは初期のLINQプロトタイプにおいて、式クォートの新しい用途を見つけました。 LINQプロトタイプは、インメモリークエリーとデータベースクエリーの両方を表現することができる、内包構文と実行時の式クォートをC# に追加しました。 内部的には、LINQは関数型プログラミングから大きな影響を受けた、クエリーのコンビネーターエンコーディングを使用していました。 LINQの主要な貢献者はErik Meijerでした。彼は関数的なアイディア全般の熱心な伝道者であり、適用においても革新的でした。 LINQは大成功を収め、今日でも広く使用されているC# の機能となりました。 また、筆者は以前IntelでForteFLを使用していましたが、これは強く型付けされた関数型言語で、式クォートを持っていました。 さらに、MathematicaやRのようなシステムは式クォートを許し、記号要素と計算要素を混在させるという興味深い用途にこの機能を利用していました。 2006年にLINQの初期バージョンが発表されたとき、筆者はF# にクォートを追加する実験をすることにしました。 当初の目的は、LINQで利用可能なクエリー機構と相互運用することでした。

実験の成果は、2006年1月26日に「F# はLINQに出会い、素晴らしいことが起こる(パートI)」というタイトルで、プロトタイプ形式でリリースされました52。 サンプルコード片は次のとおりです。

let q =
    db.Customers
    |> where <@ fun c -> c.City = "London" @>
    |> select <@ fun c -> c.ContactName @>

詳細の一部は後のリリースで変更されましたが、サンプルコード中の <@ … @> は式クォートリテラルで、式ツリーのクォートを形成しています。 プログラム中のこれらの部分は実行時に再解釈され、SQLクエリーの一部として実行されました。 このメカニズムは、より広範な「異種実行」問題にも適用されました。それは、MSRのAcceleratorライブラリーを利用してGPU上でF# コードを実行するというものです。 この研究はまとめてML Workshopで発表されました(Syme、2006)。 その後、F# 2.0では、F# クォート用のAPIの設計が大幅に修正され、簡素化されました。

2006年初頭、プラハのチャールズ大学のTomas Petricekは、F# のクォートを利用したJavaScriptコンパイラーとWebプログラミングシステムの開発に着手しました53。 2007年4月、彼はF# チームにインターンとして加わり、F# の利用例をJavaScriptとGPUコンパイルにまで広げる仕事に関わり、 2009年に再びインターンとして戻ってきて、F# 2.0に対しIDEツールを含む多くの貢献をしました。

F# 1.0 -- 機能コアの改善:字下げを認識する構文

F# 1.0期間中のもう1つの機能追加は、2006年9月23日にリリースされた54、字下げを認識する構文の追加です。

F# の字下げを認識する構文オプションは、明示的な言語構文の保守的な拡張です。 どういう意味かと言うと、パーサーにインデントを考慮させることによって in;; などの特定のトークンを省略できるだけだからです。 これはコードの可読性に驚くべき違いを生む可能性があります。

注:この機能は、PythonおよびHaskellによるインデントの使用と考え方は似ています。 なお、この機能の設計および実装手法のスケッチを手伝ってくれた、(Haskellで高名な)Simon Marlowに感謝します。 MSR CambridgeのF# ユーザー全員にも、この機能の詳細を固める手助けをしてくれたことに感謝します。

この機能の起源は、HaskellとPythonコードのサンプルを見た筆者の経験と、 非関数型プログラミングのオーディエンスから「なぜF# は let x = … inin トークンが必要なのですか」とよく聞かれることから来たものです。 筆者は、これらの余分なトークンの存在がF# の採用可能性を制限する要因であると個人的に判断しました。 この機能はその後のイテレーションによって改良され、2010年のF# 2.0でF# コードのデフォルトになりました。

F# 1.0 -- IDEツール

F# 1.0の重要な要素は、Visual Studio 2005および2008と統合するIDEツールが含まれていたことです。 このツールの初期の実装は筆者によって行われました。 ベースとなったのは、Daan Leijenによる拡張可能な言語中立ツールのプロトタイプで、それはProject 7に由来するものでした。 初期のバージョンは、デモンストレーション目的および愛好家による採用には十分でした。 しかし、このツールの実装中に多くの間違いがあり、F# コンパイラーコードベースの「コンパイラーサービス」部分の実装がすぐに不十分になりました。 これらの問題は、正確性、品質、完全性の観点から、2010年までF# ツールの妨げとなっていましたが、 2015年のF# Compiler Serviceコンポーネントの作成と2017年のその後の改善によって解決されたと言っても良いでしょう。

言語設計の観点からは、IDEツールという前提を置くことはC# の設計に強い影響を与えました。 たとえば、C# LINQの構文設計は、「人々がLINQクエリーを入力する際に、優れたIDEサポートを提供できるでしょうか?」という基本的な質問の影響を受けていました。 この仮定は、全体的にはF# 設計自体の推進要因ではありませんでしたが、時折は考慮されました。

金融業界と関数型:Microsoft、2007年にF# にコミット

2006年から2007年の間に、F# の外部からの採用が増え始めました。その理由の一部は、筆者による言語の機能と有用性についての着実なブログ投稿55です。 ソーシャルメディアと「スケーラブル」なコミュニケーションが会議の出版物よりも強調され、F# 機能セットの実用的な性質とその採用を強調するためにブログが使用されました。 オンライン開発者向けビデオポータルのChannel 9が門戸を開き、私たちはより幅広いオーディエンスにリーチすることができました56。 Windowsや.NETでの関数型プログラミングでは代わりとなる実用的な方法がないため、F# が注目を集めました57。 .NETユーザーグループは世界中に存在し、F# に関するプレゼンテーションを始めた人もいました。 ダウンロード率は2007年初頭には約18,000/年でした。主流からはほど遠いものの、MSRプロジェクトの割には比較的充実していましたし、 やや予想外でしたが、F# は research.microsoft.com の中で最も多く訪問されたサイトでした。 この言語はコミュニティに強い印象を与え、いくつかの関連技術が出現し始めました: 2006年にJon Harropが影響力のある彼の本 "OCaml for Scientists" を "F# for Scientists" 58として入手可能にしました。 2007年にAdam GraniczがWebSharperを始めました。 それには、F# からJavaScriptへのトランスパイラー、およびクライアントとサーバーの両方のコンポーネントでF# を使用する機能が含まれています59。 2007年にIntelliFactoryはF# でコンサルティングサービスを提供し始めました60 61。 2006年に、Apressの編集者であるJames HuddlestoneがSymeとPickeringに、F# に関する最初の2冊の本を執筆するよう依頼しました。 "Beginning F#" と "Expert F#"で、後者はAdam GraniczとAntonio Cisterninoとの共著です62

2007年3月までに、言語と実装は "F# 1.9" に成熟し、私たちはレドモンドで開催された社内展示会MSR TechFestでF# の更新と講演を行いました63

あと2時間で、私はレドモンドのTechFest 2007に出発します。 …James Margetson、私自身、そしてF# コミュニティの他のメンバーがブースを出展し、 F# が非常に有用なツールとして成熟したことと、革新的な関数型プログラミング応用研究の手段としても機能していることを強調してきます。

Figure 3 -- TechFest 2007でF# 1.9に使用されたポスターの1つ

中でも、Bill Gatesがブースを訪れました。 すべての研究機関と同様に、MSRはその成功を必要としており、この段階でF# を支援するべきだというのは明らかな選択でした。 筆者とMSRにいる共同研究者たちは、当言語に対するMicrosoft副社長たちの意識を高めるために「ドリップ、ドリップ」アプローチを取りました。 すなわち、電子メールと情報を定常的に転送し、隙あらばプレゼンテーションを行ったのです64。 2007年5月31日に、開発部門(「DevDiv」と呼ばれる、Visual Studioの開発部署)の責任者S. Somasegarは次のように答えました。

F# が世界中で興奮、話題、そして実案件での採用を獲得し続けていると知ってわくわくしています。 世間では関数型言語一般に対する興奮も高まっています。 関数型言語、特にF# について、私たちは何をどうすればよいと思いますか。 F# のより深いVS統合を行うために一定レベルのことを何かするべきか、考えたことはありますか。 これに関するあなたの考えを聞かせてください。

影響力のある企業顧客の中には、この言語に注目し始めた会社もあります。特に:

  • クレディ・スイスは、2006年から2007年にかけて、グローバルモデリング&アナリティクスグループという部署で、 金融商品のモデルを作成して既存のWindows COMコンポーネントと連携するために、初期バージョンのF# を試用し、導入に成功しました。
  • モルガン・スタンレーは、分析ロジックの大部分をWindowsとF# に変更し、従来のAPLコードベースを置き換えるという大規模なプロジェクトを開始しました65

2007年の夏、世界に対するウォールストリートの影響はピークに達しました。 特に、あるF# の顧客は、Windows Serverをベースにした新しい高性能コンピューティング製品である "Windows HPC" の大量購入を約束しました。 これらの企業からのF# に関するEメールは、Craig Mundie(当時のChief Research and Strategy Officer)を含む経営陣に転送され、 Mundie、Anders Hejlsberg、Steve Ballmerへのプレゼンテーションが行われました。 2007年8月、Ralf Herbrich、Thore Graepel、Phil Trelfordを擁するMSR CambridgeのApplied Games Groupが、 広告クリック数を予測する全社的な機械学習コンペティションでF# を使用して優勝しました。 Burton SmithとDave Weckerはレドモンド内の強力な支持者でした。 2007年8月30日に、Craig Mundieは次の電子メールを送信しました:

ありがとう。F# の製品化を進めます。すぐに動き出すようにSomaが後押しするでしょう。66

F# は「製品化」されることになりました。すなわち、Microsoft言語の公式にサポートされている安定版に仲間入りするということです。

F# 2.0 -- 2007 ~ 2010

実際には、Microsoftがサポートする言語になる見通しは爽快であり、かつ恐ろしいものでした。それはどういう意味でしょうか? 誰が何を確約しましたか?誰がプロジェクトを管理するのでしょうか?この言語を研究プロトタイプからどれだけ洗練する必要があるでしょうか? 誰が言語を「サポートする」立場に置かれることになるのでしょうか?誰にどんな約束がされたのでしょうか?社内の関係者は誰でしょうか? 成果はどのような基準に照らして測られるのでしょうか?これらの事柄のどれもが、最初は明白ではありませんでした。

それから6か月にわたって、プログラムマネージャーのLuke Hoban67(2007年11月1日 ~ 2010年6月)、開発者のJomo Fisher(2008年初め ~ 2010年半ば)、 エンジニアリングリーダーのTim Ng、およびQAスタッフのMatteo Tavaggi、Daniel Quirk、そしてChris Smithを含む最初のチームがレドモンドに結成されました。 Laurent Le Brunは2011年のインターンとしてケンブリッジでのテストコードの手助けをしました。 そしてJames Margetsonは、ケンブリッジで2011年3月までコンパイラーとツールの作業を続けました。 筆者は2008年2月にレドモンドチームと一緒に4週間過ごしました。

いくつかのことがすぐに明らかになりました: (ケンブリッジでも平等に人を雇うという最初の話にもかかわらず)プロセスはレドモンドから実行されるでしょう。 DevDivは、専用の「頭数」を介して資金を提供するでしょう(個々のプロジェクトに予算はありませんでした)。 持続可能で長期にわたるサポートが可能な言語を完成させるのに1 ~ 2年かかるでしょう。 適応領域として、「エンタープライズ向けの関数型プログラミング」と「テクニカルコンピューティング」に焦点を当てるでしょう。 2007年12月にニューヨークの金融機関の見学ツアーが予定され、 筆者はモルガン・スタンレー、バンク・オブ・アメリカ、クレディ・スイスなどの機関の中核となるクオンツ(定量的金融)グループに対して 関数型プログラミングに関するプレゼンテーションを自分が行うことになっていることを知りました68

しかし、すべてが順風満帆ではありませんでした。 新しい言語を使うということは物議を醸すことで、潜在的な否定的な反応を呼び起こします。 DevDivは多くの革新的なプロジェクトを進めていました。 たとえば、Iron RubyやIron Pythonなどです。.NETプラットフォームと「動的言語ランタイム」上の動的言語を推進するチームが結成されました。 これらのプロジェクトは、どちらも同胞でありながら、開発リソースの競争相手でもありました。 同様に、.NETにソフトウェアトランザクショナルメモリーを追加するための大規模なプロジェクトが開始されました。これは、一部はMSRの影響によるものです。 世界的な金融危機とその影響の中、Microsoftは2009年1月に従業員数を5,000人削減し、プロジェクトは軒並み危険にさらされ、多くのプロジェクトが中止されました69 70 71 72。 さらに、.NET自体は、以下に説明するように、その適用可能性のいくつかの限界に達すると、以前ほど純粋に積極的なまなざしを受けられなくなりました。

さらに、Microsoftのプログラミング製品は、プログラミング業界の中の比較的保守的な層に対して訴求していました: これらの人々は、関数型プログラミング言語を受け入れるでしょうか? C# は非常に強力なツールを備えた非常にアクティブなユーザーベースを持っていました。 Microsoftが長年の成長の後に驚くべきプレッシャーを受けたこのような状況では、業界に適用可能な言語としてF# を使用することは問題外とまではいきませんが、 当然のこととは言えませんでした。

そうだとすると、少なくともMicrosoftに関する限り、F# は何のためのものでしたか? 汎用言語としては、答えは「F# はプログラミングのためのものです」でしたし、今も変わらず明白です。 しかし、切り捨てるわけにいかない確立された製品範囲への追加として見た場合はどうでしょうか。 F# は、現実的には、C# 、C++、およびVisual Basicに代わるものとして、何百万もの既存の顧客に提示することはできませんでした。 主な要因は、これらのツールチェーンの「デザイナー」ツールでした。 このツールは、ユーザーインターフェーステクノロジーが変更されるたびに、構築および保守に費用がかかり、継続的な混乱を招いていました。 このツールをF# 2.0で使用できるようにすることは現実的ではないと早い時期に決定されました。 経営陣はF# が「Visual Studioの第一級言語」になるだろうと早くから伝えていました73が、 それを、すべてのVisual StudioツールがC# と同様にF# で動作するように作られるのだと受け取った人たちもいました。 2つの立場の間にある不調和は、ツールのためにMicrosoftに依存しているユーザーの間でフラストレーションを引き起こしました。 2017年に、F# ツールの大幅な改善と、Microsoft製品ラインナップでの「ビジュアル」プログラミングへの重点の減少がほぼ同時に行われ、不満は大部分が解決されました。

こう言う事情があり、F# に関連する実践的な方法論を特徴付けるために、「関数優先」プログラミングという用語を作りました。 まず 関数型プロトタイピング があり、その後に、(ソフトウェア工学と相互運用性のための) オブジェクトプログラミング と(パフォーマンスのための) 命令型プログラミング という要素が続くものです。 当時の指針としてのスローガンは、「F# はエンタープライズ向けの関数優先プログラミング」です。 さらに、一般的な経済情勢にもかかわらず、Microsoftは新しい「Technical Computing Initiative」(TCI)に投資しました。 これは最終的に300人を雇用し、まったく新しいプログラミング言語を含んでいましたが、それは決してリリースされませんでした。 F# はこれに直接関与せず、そしてTCIは3年後に主要な製品をひとつも作ることなく再編成されましたが、 しかし、F# はその公開コンテンツの一部と緩やかに連携していました。 そのため、「F# はテクニカルコンピューティング向け」、あるいは単に「F# は数学的なこと向け」というミームが生まれました -- その言い方は正しくもあり、同時に間違ってもいました。 F# の使用が成功した多くの例は技術分野にあり、特に大規模システム内に「計算エンジン」を実装するというものでしたし、 F# は、適切なライブラリーを備えていれば、MATLABまたはPythonのような言語として直接使用することも可能でした。 Harropによる "F# for Scientists" のような本は優れた初期資料であり、F# は金融業界ですでに採用されていました。 バイオテクノロジーでは、F# はJoint Genome InstituteでDNA分析に使用されていました74。 関数型言語と「数理型プログラミング」との関連付けは、長い間続いてきました。 そして、私たちはそれを避けようと努力しましたが、この通り名はしばらくの間F# に適用され続けました75

Expert F# の最初の2つの版の執筆は、2007年から2010年にかけて正確な言語詳細を洗練するのに重要でしたし、F# 2.0言語仕様の作成も同様でした。 それは、C# 言語仕様の形式で、非公式ではあるけれども厳密な200ページの文書として書かれ、多くのQA作業の基礎として使用されました76。 この間、文字通り何千もの設計提案が fsbugs@microsoft.com を介して寄せられました。当時のMicrosoftにとっては、チームと顧客の間の非常に直接的な経路です。 一方では、これは言語が発売時までに詳細に実証されていたことを意味し、他方ではチームがユーザーの要求に対応することを引き起こしました。 何百ものバグが修正され、多くの設計が改良され、そして複数の「ベータ」バージョンがリリースされました。 この間に、チーム内の役割も変わりました。 筆者はもっと「プロダクトアーキテクト」のようになる必要がありました。言語の構成に関する最終的で詳細な決定を下す役割です。 プロジェクトの重心はレドモンド(つまりアメリカ)に移り、オンライン作業とレドモンドチームに直接対面することの両方が非常に重要でした。 品質の重要性が非常に高まり、私たちは削除する機能を探すようになりました。 最終的には、F# 2.0の機能セットはF# 1.9の機能セットによく似ていましたが、言語仕様、設計、実装、およびツールの品質は劇的に向上しました。

2010年4月12日に、アイスランドの火山活動のさなか、そしてすべての関係者にかなりの負担をかけた困難な2年間の後で、 公式にサポートされた最初のバージョンである "Visual F# 2.0" はVisual Studio 2010の一部としてリリースされました77。 実際のところ、「ビジュアルな」F# は誤称です: 私たちが提供したのは、Windowsエコシステムでの採用に適した、強く型付けされたコード指向の関数型プログラミング言語でした。 これは大きな前進であり、強く型付けされた関数型プログラミングの業界における注目度を引き上げました。 しかし、それ以上のものが必要になりそうでした。

F# 2.0 -- 測定単位

2009年に1つの重要な機能が言語に追加されました。測定単位のチェックと推論です。 この研究はAndrew Kennedyによって開始されました。MSR Cambridgeの研究者で、その博士論文はHindley-Milner型推論と単位の推論を統合する方法を示すものでした78。 2007年後半、Kennedyはプロトタイプを作成し始め、2007年12月10日に作業中バージョンへのリンクが社内に送られました。 プロトタイプは翌年まで洗練され、2008年8月29日にプレビューリリースで公開されました79。 単位の推論を追加することは、Microsoft TCIの文脈では他の目標に沿ったものでしたし、 そしてそれは、他の言語では未だ実現されていない、優雅で強力かつ邪魔にならない機能でもありました。

型プロバイダーとF# 3.0

2009年12月まででF# 2.0が基本的に完成したので、MicrosoftのF# グループはF# の「次は何なのか」に急いで目を向け始めました。 2005年以来、C# は止まってはいませんでした: C# 2.0にジェネリクスとイテレーターを追加した経験(2005年)は、新しい機能の追加による言語設計の革新ということに対する、意外かつ継続的な好みを生んでいました。 C# 3.0(2008)では、C# チームが前述のLINQ(Language Integrated Queries)を導入しました。 C# 4.0(2010)では、C# チームは動的プログラミングに注意を向け、一連の弱く型付けされた機能を追加しましたが、他の機能ほど利用されてはいません。 このイノベーションの文化は、Microsoft Researchのアジェンダとも親和性が高く、後からC# に影響を与えるかもしれない新しいアイディアを提供するためにF# に目を向けた人もいました。 同様に、C# はF# に影響を与える可能性がありましたし、実際にLINQのサポートはF# 3.0に持ち込まれました。

それとは別に、F# を「製品化」するプロセスによって、筆者はさまざまな応用的プログラミングシナリオに触れました。 共通のテーマはデータの統合でした:F# や.NETの多くのアプリケーションは外部の情報源に対するプログラミングを含んでいました。 さらに、F# はF# Interactiveと呼ばれるREPLを持っていました。 そして、それはVisual Studioと共に使うことで、データスクリプティングに適したインタラクティブなエディター環境となりました。 これらのテーマをまとめると、F# はデータのプログラミング性における機能を拡張する余地があることが明らかになりました。

F# の型プロバイダーに関する作業は、Microsoft Researchで、2008年半ばのAdrian Moorsによるインターンシップから始まりました。 その時に、次のような多様なデータ指向ユーザーエクスペリエンスをサポートすることについて議論しました。

  • 「データベースの参照」(そしてその型と内容をF# スクリプティングの文脈、すなわちエディター/オートコンプリートとREPL実行の両方からすぐにアクセスできるようにする)
  • 「スプレッドシートの参照」(そして同様にその「型」と内容にすぐにアクセスできるようにする)
  • 「Webサービスの参照」(同様の効果)
  • 「CSVファイルの参照」(同様の効果)

私たちはこれをまとめて「地球を参照する」と呼びました。 しかし、そうして問題を捉えることができたといっても、これらの最初の探査は何か役に立つものにはつながらず、大きな技術的課題を解決する必要があることは明らかでした: 「強く型付けされた方法で、データを言語に取り込む」ための一般的なメカニズムについてもう一度考える必要がありました。 基本的には、スキーマ付けられた任意のデータを言語に取り込むためのメタプログラミングメカニズムが必要でした。 Jomo Fisherによるプロトタイプ作成により、コンパイル時のメタプログラミングメカニズムが生まれました。 当初は 拡張静的型付け と呼ばれ、次に 素敵な(Awesome)型 80、そして最後に型プロバイダーという名前になりました。

簡単に言うと、F# の型プロバイダーは、 ライブラリーと同じ方法でF# エディター、コンパイラー、およびREPLツールに追加される、コンパイル時のメタプログラミングプラグインコンポーネントです。 型プロバイダーは、公称的(Nominal)なオブジェクト型定義と、関連するプロパティおよびメンバーによる、プログラムで生成された空間に関する情報を提供します。 また、これらの型のメソッドの削除された実装を表すマクロ展開も提供されています。 このメカニズムは「オンデマンド」の方法で機能したので、型プロバイダーは関連する公称的型の無限の海を供給できました。 これにより、驚くほど多様な応用が可能になり、応用に関する魅力的な議論が業界のさまざまな分野の人々と行われました。 不思議なことに、これらの会話のほとんどはプログラミング言語の研究者とのものではありませんでした!

初期のデモはFisherによって開発され、2010年2月17日に社内伝達されました。 息をのむような感動と爽快さを感じました -- 私たちは次のようなことを瞬く間に実演してみせたのです。

  • Excelスプレッドシートの、オートコンプリートと型チェックを伴うF# プログラミングへの即時統合。
  • Freebaseと呼ばれるエンティティグラフ81のようなスケーラブルなセマンティックウェブの情報ソースの、オートコンプリートと型チェックを伴う即時統合。
  • 複数のデータベースを、強く型付けされた形でデータスクリプト内から直接参照。

F# の型プロバイダー用に最初に社内配布されたデモスクリプトと画面キャプチャーは次のとおりです。

  1. 次のように対話的に入力して実行する: #r "FSharp.Data"
  2. MySpreadsheet.xlsx を開く
  3. FSharp.Data. と入力する
  4. 続けて入力し、 FSharp.Data.Live.Excel.MySpreadsheet.Invoice. とする
    • データを含むセルが表示されることを示す
    • データチップにシートの実際の値が出ることを示す
    • 'string' 型がExcelからF# に伝わっていることを示す
  5. MySpreadsheet の上にカーソルを置くと、参照しているファイルの完全なファイル名と、スプレッドシートからのコメントが表示される
  6. Excelのコメントを開き、データとコメントの出所を確認する
  7. RowsByNamedColumn を表示する
  8. ループさせて表示するようコーディングするが、その際にループ変数に対するドットでメンバーを確認できることを最初に示す
  9. ドットを削除し、インタラクティブに実行する
    {Quantity=5, Unit=car, Description=Ford GT40, Unit Price=148000, … }
    {Quantity=1, Unit=banana, Description=Yellow and curved, Unit Price=0.99, … }
  10. Freebaseに移動し、トップレベルドメインの大規模な集合を表示する
  11. 何かを検索する

これはF# 2.0でしたが、上記の例から明らかなように、IDEに統合されたツールを使用して、非常に豊富なデータソースに瞬く間に接続しました。 さらに、これらのプロトタイプは、「実際に」業界に提供できる言語とIDEツールを前提として作成されていました。 2010年6月までに、私たちはF# の金鉱をいくらか掘り当てるだろうとわかっていました。 この機能は、実際的な顧客の懸念に対処したものでした。簡単にデモできました。革新的でした。 異なるデータソース用に個別のツールを用意する必要性を回避しました。データ統合の観点で、F# が他の言語から抜きんでることを可能にしました。 さらに、この機能は、研究と製品の間の「格差を超えて」、MSRとMicrosoft製品チームの間の継続的な協力を可能にするものでした。

2011年、MSRとMicrosoftの両マネージメントは、型プロバイダーをF# 3.0の主要部分にすることを確約しました。 2010年から2012年までの期間は、メカニズムの改良と、F# と一緒に機能する一連の型プロバイダーの提供に費やされました。 Try F# と呼ばれるオンラインデモが作成され、Microsoft External RelationsのTony Heyによって資金提供されました。 F# 3.0には、LINQクエリーのサポートの強化、その他のさまざまな改良や修正も含まれています。 この間、Sarika Calla、Donna Malayeri、およびLayla Driscollがプログラム管理を担当しました。 Joe Palmer、Brian Macnamara、Dmitry Lomov、Vlad Matveevが開発スタッフで、Matteo TavvaggiとLincoln AtkinsonがQAスタッフでした。 Kevin Ransomは、F# 3.0の終わり頃にチームに加わり、.NETとVisual Studioの開発当初から取り組んできた豊富な経験をもたらしました。 Keith Battocchi(2011 ~ 13)およびRoss McKinlay(2013)は、型プロバイダーの応用に関してMicrosoft Researchから委託されて作業し、 Microsoft Dynamics CRMとWindows WMIコンピューター管理情報の統合を含む、Microsoft製品ラインナップに潜在的に関連する型プロバイダーの応用を開発し、 MSR TechFest 2012および2013で発表しました82

2012年9月12日にF# 3.0がリリースされると、F# 型プロバイダーはすぐにF# エコシステムの重要な部分となり、 後にTomas PetricekとGustavo Guerraによって、XML、CSVおよびHTMLデータに共通的に使えるFSharp.Dataライブラリーが作成されたことでもその効果が確認されました。 型プロバイダーのその他の用途は次のとおりです。

  • データベース統合(SQL)
  • 言語統合(T-SQL、Rプロバイダー)
  • 構成情報統合(FSharp.Configuration)
  • Web API(JSONおよび、WSDLやSwaggerなどのスキーマ付けを利用)
  • Hadoopを含む、スキーマ付けられた「ビッグデータ」ソース

データを元にした型 -- 構造化データをF# の第一級市民とする (Petricek, Guerra, & Syme, 2016)という論文は、PLDI(訳注:Programming Language Design and Implementation、計算機学会ACMのプログラミング言語分科会SIGPLANが主催する会議) 2016でDistinguished Paper賞を受賞し、 2018年にCACM(訳注:Communications of the ACM、計算機学会ACMの学会誌)が選ぶ3つの研究ハイライトのうちの1つに選ばれました。

.NET、F# 、そしてクラウドおよびモバイルコンピューティングへの移行

本稿の焦点は、F# の初期、特に2012年のF# 3.0までの歴史、および将来のF# 言語のすべてのバージョンのバックボーンを形成してきた革新的な機能のコアセットにあります。 本稿の残りの部分では、2012年以降の最新の歴史について説明しますが、詳細については少し割愛し、 特に、初期の歴史の中でも登場していましたが、その後大きな変化が起こったテーマに焦点を当てます。

F# 3.0の期間中、MicrosoftでF# 、C# 、および.NETのすべてが順風満帆だったわけではありません。 これは主に、モバイルコンピューティングとクラウドコンピューティングの台頭に伴う、業界内の地殻変動によるものでした。 iPhoneは2007年に発売され、業界に大きな変化をもたらしました。 2011年頃、.NETはMicrosoft内部で深刻な困難に突き当たりました。 Windows 8に向けて、Windowsチームは、「コンシューマーアプリ」のモデルがiPhoneおよびiPadで非常に成功していることを踏まえて、プログラミング性を再評価する必要がありました。 その一環として、WindowsチームはHTML5とJavaScriptをWindowsプログラミングの第一級言語として採用することを決定し、 Windows 8は最終的に「Windowsストア」アプリの主要なプログラミング言語としてC# 、JavaScriptおよびC++ をサポートしました。 これは多くの外部の観察者によって、Windowsストアアプリ開発で最も人気のある言語がC# であったにもかかわらず、.NETからの「後退」として見られました。 この認識は、ブラウザーでホストされる.NETのバージョンであるSilverlightの開発が中止されたときに強化されました。 さらに、iPhone、iPad、およびAndroidからの脅威を受けて、Windowsチームは企業ではなくコンシューマーアプリケーションに焦点を当てたいと考えました。

MicrosoftのF# にとって、これは一連の困難な問題を引き起こしました。 エンタープライズ部門が「プラットフォームの乗り越え」を通じて企業利益の最大95%を維持しているにもかかわらず、 エンタープライズ向けプログラミングが企業戦略にとって重要ではなくなった当時、 同社の製品範囲内でF# は「エンタープライズ向け関数型プログラミング」として位置づけられていました。 政治的な理由から、強力なWindowsチームに対しDevDivは、F# をアプリケーションプログラミングの選択肢としてプッシュすることができないと感じました。 幸いなことに、F# はDevDivから引き続き良いサポートを受けていました。 リソースの削減が発生し、大きなプレッシャーがかかる一方で、チームにはF# 3.0機能セットを高品質で提供するためのリソースが与えられ、その後F# 3.1などが提供されました。 しかしながら、コンピューティング環境の中で物事が間違いなく変化し、Microsoftの多くのプロジェクトが影響を受けました。 Steve JobsがiPhoneで成功したことから、Microsoftの多くのテクノロジに圧力がかかるという因果関係もありました。

幸いなことにこの頃、Microsoftの大きな構造的変化が、Azureクラウドプラットフォームの開発と共に起こりました。 Azureはもともと2010年にリリースされましたが、2012年から成熟を達成し、商業的成功を高めました。 Amazon Web ServicesやGoogle Cloud Platformなどのプラットフォームでも、サーバー側のコモディティコンピューティングへの移行が起こりました。 クラウドのプログラミング性は、高級言語と関数型プログラミングの両方に非常に適しており、 2012年から、F# の将来にとってAzureとクラウドコンピューティングが重要な部分であることが明らかになりました。 同じことが.NETにもより一般的に適用され、Azureは.NET、C# 、およびF# の技術的戦略にますます影響を与えるようになりました。 Azureは、プログラミング言語、SDK、およびAzureへのアクセスに使用されるツールでオープンソースを完全に採用したため、Microsoftにも大きな変化をもたらしました。 現時点で、MicrosoftはAzure内でのLinux利用も全面的に受け入れていました -- 10年前には考えられなかったことです。 Microsoftは現在Linuxを「愛して」おり、そしてそれは成長ビジネスの1つの中心的な部分を形成しました。

この間、アテネのコンサルタント会社Nessosは、MBraceと呼ばれる非常に革新的なクラウドプログラミングシステムを開発しました (Dzik, Palladinos, Rontogiannis, Tsarpalis, & Vathis、2013)。 もともとは分散プログラミングシステムと考えられていましたが、その後の発展ではクラウドコンピューティングとビッグデータ処理が強調されました。

F# 、C# 、.NETの新しい黎明期:オープンとクロスプラットフォーム、ついに登場!

登場以来、F# は最も重要で、一見したところ克服できない課題に直面しました。 オープンソースソフトウェアが一般的になり、プログラミング言語やランタイムの世界では.NET、F# 、およびC# が明らかな異常値となりました: 大部分がクローズドソース -- あるいは少なくとも外部の貢献を受け入れていない -- という理由です。

Microsoftには、オープンソースを採用することを提唱する人が多くいましたが、.NETの登場以来、その背景には疑問が潜んでいました。 2004年には、.NETの「シェアードソース」バージョンがリリースされました。 F# のソースは、初期のMSRリリースにも含まれていましたが、非商用ベースでした。 しかし、オープンソースはまだ物議を醸しており、いくつかの例では、プロジェクトはすぐに中止されることを目的にオープンソース化されていました。 そのため、「オープンにする」ことは依然として危険であり、慎重に説明する必要がありました。

2010年11月11日に、MicrosoftはOSI認定ライセンス(Apache 2.0)の下でF# ソースの最初のリリースを行い、F# は今後より広く受け入れられるであろう変革の先駆者になりました83。 さらに重要なことには、2014年4月3日にMicrosoftはF# への貢献を受け入れ始めました。 これもまた、完全なオープンエンジニアリングプロセスを採用する上で「先駆的」でした84。 これに対応して、オープン設計へ向けた移動も可能になり、F# 4.0では、言語設計はオープンで透明なプロセスに移行しました85。 言語設計プロセスとRFCは、筆者、Phillip Carter(MicrosoftのF# のプログラムマネージャー)、そしてChet Huskの指導の下、FSSFを通じて運用されます。

オープン性への移行は他の効果ももたらしました: 2013年、NuGetパッケージマネージャーとnuget.orgパッケージリポジトリーが作成されたことで、.NETコミュニティはついにパッケージを提供するための現代的で効果的な方法を開発しました。 これ以前は、.NETコンポーネントのパッケージ化がうまくいかなかったことが、.NETとF# の両方の成長を妨げる大きな要因でした。

2014年に、PetricekによってFSharp.Compiler.Service(FCS)パッケージが作成され、その後多くの貢献者が参加して技術的な進歩がありました86。 これには、F# コンパイラー、エディターツール、およびスクリプトエンジンのコア実装が単一のライブラリー形式で含まれており、さまざまな状況でF# ツールを使うことができます。 これにより、F# をさらに多くのエディター、スクリプト作成および文書化ツールに配信することが可能になり、F# の代替バックエンドを開発することが可能になりました。 コミュニティベースの主要なツールには、Cieslakとその他貢献者によるIonideがあり、クロスプラットフォームのVSCodeエディターでリッチな編集をサポートするために使用されています87

今日、オープンソースはMicrosoftのほぼすべての言語およびクラウドツールの基準です。 コアF# ツールは貢献を受け入れ、多くの貢献者を持っています。 NuGetパッケージエコシステムは、現在120,000以上のパッケージをホストしており、約100億のパッケージがダウンロードされていて、 世界で最大かつ最も包括的なパッケージエコシステムの1つになるほどに急速に成長しています。 オープンソースのPaketクライアントはF# 開発者がこのエコシステムにアクセスするための一般的な方法であり88、 オープンソースのFAKEビルドスクリプトツールはF# を採用するための「ゲートウェイドラッグ」です89

F# コミュニティとF# ソフトウェア財団

F# コミュニティは当初、Chris Barwickによって "optionsScalper" という仮名で作成された hubFS.net フォーラム(2005年)を通じて支えられていました。 F# のオンラインコミュニティ(2007)は、Ryan Rileyによって作成されました。 2012年のSkillsMatter Londonミートアップの開始は、英国とヨーロッパでF# コミュニティの成長を推進し、2018年までに50を超えるF# ミートアップグループが世界中で作成されました90。 コミュニティ主催のF# カンファレンスにはopenfsharp、F# Exchange、fableconfがあり、F# の資料は.NET寄りのカンファレンスと関数型寄りのカンファレンスの両方で定期的に発表されます。 2011年に、hubFSフォーラムは、Adam GraniczとIntelliFactoryの人々らに実装されたFPish.netで置き換えられました。

2014年には、Tomas PetricekとPhil Trelfordがケンブリッジのカフェで筆者と会い、F# Software Foundation(FSSF)を設立することを決定しました。 これは一般に "fsharp.org" として知られています。 当初、これはPython Software Foundationの方針に沿った非公式の組織でした。 潜在的なコミュニティメンバーのオンライン会議が開始され、PetricekとTrelfordは彼らの目標を説明しました。 F# ユーザーの興味を表すことができる、楽しくてオープンなWebベースの組織です。 参加は無料で、組織の使命声明に対する合意のみが必要で、約500人の会員に急成長しました。 2016年にFSSFはReed CopseyとMathias Brandewinderの指導の下に米国の非営利団体として法人化し、現在は年に一度の委員会選挙を開催しています。

FSSFの形成はF# にとって非常に重要な瞬間でした。 それまでは、.NETおよびF# コミュニティに強い「依存の文化」があり、 (有料顧客を含む)ユーザーはMicroosftがすべての問題を解決し、すべてのリソースを提供し、 これらのテクノロジに関するすべてのパブリックコミュニケーションを行うことを期待していたました。 FSSFが形成されたことで、この状況は変わりました: F# コミュニティは、社会的実証を収集し、F# の使用をサポートし、コミュニティのエンジニアリングに関する取り組みを手助けする強力な発言者を得ました。 その結果、F# の伝道はより効果的になり始めました。 F# の伝道におけるコミュニティのより積極的な役割の結果の1つは、Scott Wlaschinによる「F# for Fun and Profit」の作成です。 このサイトは、F# コミュニティで非常に影響力のある、関数型プログラミングの概念および実用的なF# トピックに関する教訓的な資料のコレクションです。

FSSFは現在2,000人以上のメンバーを持ち、fsharp.orgとgithub.com/fsharpを所有しています。 FSSFは現在F# コミュニティの中心にあり、コミュニティの利害関係者と協力してF# の教育、多様性、ツール、ガバナンス、会議、およびソフトウェアのイニシアチブについて取り組んでいます。

.NET Core:MicrosoftがC# 、F# 、.NETをクロスプラットフォームに

.NETに対するクロスプラットフォームサポートの問題は最初から存在していました:2004年のシェアードソースリリースでもクロスプラットフォームでした。 同年、Miguel de IcazaらによってMonoプロジェクトが開始され、.NETの完全にオープンソースでクロスプラットフォームなバージョンが実装されました。 F# は2006年以来Mono上で快適に動作しました。

2016年に、Microsoftは.NET Coreという、完全にオープンソースでクロスプラットフォームな.NET実装をリリースしました。 F# のサポートは.NET Core SDKに直接含まれており、標準のLinuxパッケージにも含まれています。 v2.0がリリースされたことで、.NET Coreはますます成功を収めており、F# をLinuxおよびDockerで使うことは現在コミュニティ内で主流になっています。 AmazonやGoogleなどのクラウドプロバイダーは現在、.NET Coreを通じてF# をサポートしています。 これは、Azure Functions、Amazon Lambda、Google Cloud Platformなどのクラウドホストサービスでの.NETサポートのバックボーンを形成しています。

.NET Core SDKに直接F# を含めることは、この言語の歴史において最も重要な長期的イベントの1つです: F# は、.NET Core SDKがインストールされているすべての場所で、シンプルで一貫性のある方法で完全にサポートされますし、 オープンソースコミュニティと主要な商業的関心の両方からの支援もあります。 さらに、.NET Coreにより、そのプログラミングフレームワークは、Windowsエコシステム内での後方互換性に伴う非常に厳格な制約がいくつか取り除かれ、 ランタイムレイヤーへ迅速に新機能を導入することが可能になりました。 .NET Coreでは、並立インストールが可能であり、ランタイムの変更は同じマシン上の既存のアプリケーションには影響しません。 これにより、ランタイムとその言語の共進化が可能になります(もともとF# に影響を与えたOCamlの、長所の1つでありつづける特徴です)。 これは、C# とF# の設計にすでに影響を与えています。C# 7.2とF# 4.5のSpan機能には、ランタイム要素と言語要素の両方が含まれています。

モバイル用途のF#

業界がモバイルおよびクラウドコンピューティングに移行したことで、2009年以降、プラットフォームとしてのAndroidおよびiOSの重要性が大幅に高まりました。 .NETを使用している何百万人もの人々に向けて、Xamarinと呼ばれるスタートアップが結成され、 C# とF# の開発者が既存のスキルを使ってAndroid、iOS、そしてWindowsデバイス用のアプリケーションをプログラムできるようになりました。 Xamarinツールチェーンは.NET ILコードをJavaコード(Android用)とバイナリーコード(iOS用)に変換します。 Xamarinはクロスプラットフォームのユーザーインターフェースプログラミングに、Xamarin.Formsを含む選択肢も提供しました。

Xamarinは最終的にMicrosoftに買収され、2018年の時点でF# はMicrosoftのモバイルプログラミング製品でサポートされている言語となっています。

F# 、JavaScript、そしてフルスタックプログラミング

2005年以来、JavaScriptはプログラミング言語の配信プラットフォームとして重要性を増しています。 2007年に、Tomas PetricekはF# の最初のトランスパイラーを試しました。2008年にWebSharperの最初のバージョンがリリースされました。 当時革新的だったWebSharperは、F# を主要なプログラミング言語として使用した、完全なオープンソースのフルスタックプログラミングツールキットです。

2015年には、F# コミュニティは、JS / NodeエコシステムでのWeb開発のために、F# のもう1つのJavaScript実装であるFableも開発しました(García-Caro、2018)。 これを書いている時点で、FableはWebプログラミングでの採用が増えています。 Fableは、Webクライアント、サーバー、クラウドコンピューティングを組み込んだF# 用の「フルスタック」ソリューションであるSAFE-Stackの主要部分となりました。

回顧

F# の起源と初期の歴史を語る際に、1990年代半ばに業界を巻き込んだJavaとオブジェクト指向プログラミングの波、そしてJVMと.NETの台頭に対する、 強く型付けされた関数型プログラミングを経験した人々によるいくつかの「反応」の1つとして位置づけました。 この観点から、関数型言語をどのように提供するかを変えることに先駆的だったのがF# でした。 F# とScalaは、JVMや.NETなどの業界標準の仮想マシン基盤を想定して明示的に設計および実装された最初の言語です。 後になって考えれば、この決定は良いものでした。 そしてその後Clojure、Nemerle、KotlinとSwift(Swiftは基盤としてObjective-Cランタイムをターゲットにしていますが)を含む多くの言語が続きました。 最近の言語の波は、JavaScriptを基盤としています(例:Elm、TypeScript、PureScript)。 このアプローチは今や非常に一般的になり、新しい言語の取り組みにおいて業界標準となっています。

プログラミング言語は多くの目的に使われるようになり、人々がF# を使って行った多くの魅力的なことを公平に評価することは不可能です。 FSSFの初期の作業の重要な側面は、利用者の声を通してF# の有効性についての「社会的実証」を収集し伝達することでした91。 しかしながら、3つの用途は特に印象的です。 まず、LIQUi|>( "Liquid" )の実装にF# が使われました。これはF# の量子シミュレーターで、Dave WeckerとMicrosoft Quantum Computingの手によるものです92。 次に、F# とRhinoceros 3Dとを組み合わせて使うことで、Louvre Abu Dhabi Domeの外装の製造に使用されるデジタル3Dモデルが構築されました。その写真を図4に示します。 第3に、F# はJet.comで使用される主要言語です。 Jet.comは、その後Walmartが$ 3B以上の評価で買収したスタートアップ企業で、Azureクラウドプラットフォームを使用して構築された最初の「ユニコーン」です。 これらだけでも、1998年の規模を超えた強く型付けされた関数型プログラミングの成功を構成します。

Figure 4 - The Louvre Abu Dhabi - the digital 3D model to manufacture the cladding used F#

2007年頃から、強く型付けされた関数型プログラミングは、無名の存在からプログラミングの中心的なパラダイムへと移行しました。 C# 、Java、C++ 、Scala、Kotlin、Swift、Rust、およびTypeScriptには、すべて強く型付けされたFPの要素が含まれています。 そしてAppleの幹部らは、2014年のSwiftのローンチ時にパターンマッチング、ジェネリクス、オプション型、型推論、タプル、クロージャーといった関数型の機能を称賛しましたが、 それは2005年だったら考えられないことでした93。 Haskell、F# 、OCamlはいずれも普及してきており、そしてElmやReasonMLのような新参もまた採用が進んでいます。

この変化の原因は何だったのでしょうか? 本稿ではいくつかの要因について説明しました -- ウィジェットベースのGUIプログラミングが相対的に減少し、それに対応してWebプログラミング、 クラウドコンピューティング、マルチコアプログラミング、およびスケーラブルデータ処理などが増加しましたが、それらのすべてが関数型プログラミングに適しています。 JavaScriptの重要性の高まりもまた確実に関連性があります: 型はありませんが、JavaScriptは多くの関数的な特徴を持っています。 とは言え、ScalaとF# が成熟し、コンピューティング業界の中心でサポートを受けるようになったころに移行が始まったようにも思われることは注目に値します。 Swift、ReasonML、TypeScript、Elmなどの最近の参入者は多くの課題に直面していますが、 それらの課題の中には、強く型付けされた関数型プログラミングについて業界の認識が足りないというものはもうありません。 私たちは2007年以来長い道のりを歩んできました。 そしてWadlerの「なぜ誰も関数型プログラミングを使わないのか」という質問は、短命だった疑問のひとつとして歴史の中に埋もれていきました。

F# の影響

F# が最も明白に直接的な影響を与えたのはC# です。 C# 2.0(ジェネリクス)はF# の作成に至るまでの予備作業でした。 C# 3.0(var x = …)、C# 5.0(タスク/非同期)、C# 7.0(タプル、パターンマッチング)およびC# 8.0(非Nullポインタがデフォルト)はすべてF# の影響を強く受けていました94。 C# が今日最も広く採用されている言語の1つであり、2000年代に急速に進歩を繰り返した95ことを考えると、 Microsoft Developer Division内のF# の存在が、「関数型プログラミング」の一連のアイディアとC#とをつなぐ架け橋として重要な役割を果たしたと主張しても過言ではないでしょう。 とはいえ、アイディアは両方向に流れてきました。F#はC# 1.0(オブジェクト、プロパティ、イベント)、C# 3.0(LINQ)、C# 7.0(Span)の影響も受けています。 F# 以外の他のソースもC# に影響を与えました。たとえば、Icon(C# 2.0イテレーター)、Python(C# 4)、 Gustafssonらによる内部プロジェクトAxum96(C# 5.0の非同期をステートマシンにコンパイルする機能)、M#97 (C# 7.0のSpan)などがあります。

ファーストクラスのイベントと合成可能なイベントコンビネータープログラミングをF# に追加したことは、 リアクティブ関数型プログラミングツールキットであるRxプロジェクトの開始に直接影響を与えており、 現在それは、RxJSを含む複数の言語でパターンとして再実装されています98。 この件における初期のF# の影響は、Wes Dyerから筆者に非公式に説明されました。

他の言語に対するF# の直接的な影響は測定が困難です。言語デザイナーは、直接的であれ間接的であれ、両方の影響を言おうとしない傾向があるからです。 ElixirとElmはどちらも |> 演算子を使用しており、ScalaやRなどの他の言語ではその演算子をエミュレートする方法があります。 Scalaの設計者であるMartin Oderskyは、MSR CambridgeのテクニカルアドバイザリーボードやEPFLの研究での彼の役割において、 F# の歴史を通してF# を密接に認識していました。なお、その中にはF# の型プロバイダーをScalaにもたらす努力が含まれます99。 Scalaにおける抽出子の作成に対するF# の明らかな影響については、本稿の前半で説明した通りです。 SwiftはF# の影響を受けているようですし、KotlinはC#、F#、その他の言語を参照点として使用しているようです。 RustはOCamlの影響を受けているように思われます。筆者のGraydon Hoareは、Rustの後の「次は何か」について議論するときにF# を広範囲に参照しています100。 TypeScriptはF# の影響を直接受けていました:TypeScriptの創始者の1人にLuke Hobanがいて、彼はF# 2.0に関わった直後にTypeScript(当時はStradaと呼ばれていました)を始めました。 最近彼は、TypeScript設計の初期の部分におけるF# の影響について指摘しました101。 影響がどの程度あったとするのかは反事実的状況を仮定した議論になってしまいますが、 F# の影響がなければ、TypeScriptが現在の形に近い形でMicrosoftのチームから登場してはいなかっただろうというのが筆者の意見です。

最初から、F# はNullを排除することを設計の中心としていました: 値 "null"は通常、F# で宣言した型と組み合わせて使用することはできず、実際にはNull参照例外はまれです102。 これは当言語における多くの細かな決定に影響を与えています。 OCamlの観点から言えば、これは明らかな選択であり、 MSR Cambridgeの文化的文脈 -- 研究室でのTony Hoareの存在および彼の「10億ドルの間違い」の名言を含む -- では、他の選択は考えられなかったでしょう103。 しかし、Scalaのような言語は同じ決断をしなかったので、2014年にいたるまで、JVMまたは.NET上で実行され、設計の中心にNullの排除が置かれている重要な言語は、唯一F# だけでした。 2018年8月の執筆時点では、C# 8.0は非Nullをデフォルトにすることを計画しています。 この劇的な変化が、Nullという癌をプログラミング業界から排除するための変化をもたらすだろうと私たちは願っています。 このプロセスの中心にあり続けたのはF# です。

F# は、言語の既存の制御構造の局所的な再解釈を可能にするために "async" モダリティを導入した最初の言語です104。 つまり、コードの一部を「同期」から「非同期」に変換するのに必要なことは、コードを「async {…}」で囲み、 呼び出し元の地点を「await」(F# では「let!」)でマークアップすることだけでした。 これは、2012年にC# 5.0に追加されたasync/awaitメカニズムに直接影響を与えました -- F# バージョンがC# デザイナーに最初に紹介されたのは2007年でしたが、2012年までの間に多くの議論が行われました。 C# のasync/await機能は、TypeScript、Kotlin、その他の言語に影響を及ぼしています105

間違いと課題

間違いを認めるのは困難であり、歴史的文脈で最もよく見られます。 初期の歴史から振り返ると、F# に関する最大の間違いは、.NETと言語がオープンソースでもオープンエンジニアリングでもなかったことです。 当時の中心的な貢献者たちはこの間違いをよく理解しており、Microsoftの多くの人がオープンソースへの移行を主張していました。 簡単に言えば、ある革新的な言語がオープンソースをまだ採用していない企業の研究室で生まれたということです: 関係者はソースドロップを通じてできる限りのことを行い、最終的に2011年から2014年にかけてオープンソースに移行しました。 この間違いの修正は、おそらくこの言語の歴史の中で最も重要な発展となるでしょう。 さらに、F# がクローズドエンジニアリングを使用しながら2002年から2014年まで進むことができたという事実は、主にMicrosoftの意思決定者によるその品質の認識によるものです。

クローズドエンジニアリングの不幸な副作用の1つは、不連続性でした: F# への初期の貢献者のほとんどは、すぐに他の仕事に移りました。 F# はオープンソースではなかったため、過渡的であってもコードベースに貢献し続けることはできませんでした。 今日では、貢献者は自由に行き来し、比較的古いコードに関する質問にも頻繁に答えることができます。

技術的な観点からは、F# には多くの実績があり、F# 1.9以降、コア機能セットは安定しており、バイナリー互換性さえありました。 もちろん、アクティブなバグを含む、設計上の誤りはいくつかあります。 これらのうち、「静的に解決される型パラメーター(SRTP)」のメカニズムは、おそらく最もコーナーケースのいらだちを引き起こす機能です。 もともと演算子のオーバーロード専用に設計されたこのメカニズムは、F# の上級ユーザーによって、Haskellの型クラスに似た型制約メカニズムとしても使用されています。 ただし、複雑なSRTP制約とアルゴリズムベースの型推論との組み合わせは脆弱であり、 SRTP制約の解決におけるいくつかの誤りは、既存のコードをコーナーケースで壊すことなく修正するのは困難です。 後方互換性がそれほど問題にならないのであれば、これは問題にならないでしょう。 しかし、F# コミュニティとMicrosoft設計グループの両方から、後方互換性は非常に重視されています。

F# の設計にはOCamlのいくつかの機能が組み込まれていましたが、振り返ってみると省略しても良かったのではないかというものがあります。 一つの例は、ジェネリックな比較です: OCamlは制約のないジェネリックな構造的演算子 =<><><=>=compareminmax をサポートしています。 F# 設計では、これらの演算子に "equality" および "comparable" の型制約が適用されますが、 特に、浮動小数点数の NaN のようなコーナーケースのため、ジェネリックな比較の実装は実行時に複雑になります。 これらの演算子を使用すると、パフォーマンスにも影響があります。 振り返ってみると、ジェネリックな比較機能全体がF# では省略されているか、大幅に制約されていても良かったように思えます。

F# 言語進化で繰り返されてきたテーマの1つは、対応するC# および.NET 設計要素との相互作用です。 たとえば、F# 1.9は2007年に Async<T> を追加しました。 対照的に、.NETは2010年に Task<T>を追加し、C# 5.0は2012年に Task<T> の言語統合サポートを追加しました。 高い視点からは、これらはすべて「同じもの」、つまり軽量なユーザーレベルスレッドです。 しかし、2018年、すなわち執筆の時点でさえ、これらを一緒に使うのにはぎこちなさがあります。 それらを相互運用することはできます: Async<T> から Task<T> を生成し、Async<T> の中で Task<T> を待つことができますが、それぞれに個別の利点があります (Async<T> を使用する場合、F# プログラマーは明示的に取り消しトークンを渡す手間が省けますし、 Task<T> を使用すると、パフォーマンスに影響するヒープ割り当て量が少なくなります)。

1つの小さいながらも偶然の間違いは、「逆パイプライン」演算子 f <| x の優先順位でした。 これは、左結合の優先順位のため、f2 <| f1 <| x と繰り返し使用することはできません。 これは意図的ではありませんでした -- 優先順位は単にOCamlから取られました -- しかしF# で優先されるスタイルは x |> f1 |> f2 なので、修正はされませんでした。 ですので、この間違いには逆パイプライン演算子の使用を制限するという利点があると言えます。 F# のライブラリーは、複数引数の逆パイプライン演算子 <||<||| を含みますが、それらは単にスタイル上の理由で含めるべきではありませんでした: それらを使用したコードは非常にまれなだけでなく、不可解です。

F# がある機能の1つのバージョンを追加し、後にC# だけが同様の機能の修正版を追加するという緊張は、タプルでも繰り返されました: F# は2002年に、ボックス化されるタプルを初めから持っていましたが、C# は2017年にボックス化されないタプルを追加しました。 2017年に、F# 設計チームは、ボックス化されるタプルとボックス化されないタプルの両方を許可するようにF# を調整する必要がありました。 2007年のC# 式クォートの導入も同様でした: F# には Expr<T> というクォートがありますが、C# に追加された式クォートはLINQの Expression<T> であり、.NETライブラリーで広く使用されています。 C# 式のクォートは、厳密にはF# クォートよりも制限され(C# 式のみを対象とし、ステートメント形式は対象外)、より複雑ですが、事実上.NET標準です。 筆者の知る限りでは、他の言語が「より大きな」言語とこんなに近い距離でダンスすることはありません。 F# 設計の長期的な整合性にとって、これらの調整は細心の注意を払って行われることが重要です。

言語設計として、F# は進化できる可能性を多く残していますし、 公式のFSSF言語設計プロセスの一部を形成する「F# 言語提案」サイトには、200以上の活発な言語提案が記録されています106。 最も人気のある提案は、型クラスと、高カインド型パラメーターの2つです。 ただし、どちらのケースも、C# に一致する機能を追加せずに、F# にこの機能を追加することは避けたいと筆者は述べています。 それは部分的には、似ているけれども互換性が不十分な機能が複数生まれるというパターンの繰り返しを避けるためです。

.NET Coreに関する説明で示したように、C# と.NETランタイム自体の両方の設計と関連して、重要な進化のステップが発生する可能性があります。 一例として、F# 4.5とC# 7.2に "Span" と呼ばれる安全で高性能なメモリープリミティブが追加されました。 この機能には、F# 2.0の設計以降に存在するさまざまな小さな問題を解決するのに役立つという追加の利点がありました。

結論

本稿では、1970年代のRobin Milnerから今日のF# までの長い弧を、F# の起源と初期の歴史、そしてそれが起こった背景に焦点を当ててスケッチしようとしました。 F# は、OCamlメーリングリストの電子メールにおけるアイディアだった2001年、Microsoft Researchプロジェクトだった2006年、 F# 2.0がWindowsに効果的に結び付けられていた2010年を経て大きく進歩しました。 その過程を通して、MLのコアスピリット -- 簡潔で、型安全で、正しく、実用的な関数型プログラミング -- は、新しいアイディアと統合されながらも真実であり続けました。 今日のF# はオープンソースでクロスプラットフォームであり、商用サポートと活気あるコミュニティの両方を備えています。 それは確固たる将来の進化の道を持ち、実用的で楽しい関数優先プログラミング言語として多くの応用分野で使用可能です。

謝辞

この文書の初期の草稿に対するフィードバックについて、Andrea Magnorsky、Phillip Carter、Darren Platt、Natallie Baikevich、Richard Campbell、 Adam Granicz、Tomas Petricek、Mark Laws、Miguel de IcazaおよびSimon Peyton Jonesに感謝します。 残っている間違いはすべて筆者の責任です。 これは最初のドラフトなので、追加情報や修正はできるだけ早く筆者に連絡してください。

参考文献

  • Alves-Foss, J. (1999). Formal Syntax and Semantics of Java. Berlin: Springer-Verlag.
  • Benton, N., & Kennedy, A. (1999). Interlanguage working without tears: blending SML with Java. In ACM SIGPLAN Notices - ICFP '99 Proceedings of the fourth ACM SIGPLAN International Conference on Functional Programming (pp. 126 - 137). ACM.
  • Benton, N., Kennedy, A., & Russo, C. V. (2004). Adventures in Interoperability: The SML.NET Experience. In PPDP '04 - Proceedings of the 6th ACM SIGPLAN International Conference on Principles and Practice of Declarative Programming (pp. 215-226). ACM.
  • Bracha, G., Odersky, M., Stoutamire, D., & Wadler, P. (1998). Making the future safe for the past: Adding Genericity to the Java Programming Language. In Proceedings of the 13th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (pp. 183-200). ACM SIGPLAN Notices.
  • Cardelli, L., & Abadi, M. (1996). A Theory of Objects. New York: Springer-Verlag.
  • Duffy, J., & Sutter, H. (2008). Concurrent Programming on Windows: Architecture, Principles, and Patterns. Addison Wesley.
  • Dzik, J., Palladinos, N., Rontogiannis, K., Tsarpalis, E., & Vathis, N. (2013). MBrace: Cloud Computing with Monads. In Proceedings of the Seventh Workshop on Programming Languages and Operating Systems. New York: ACM.
  • Emir, B., Odersky, M., & Williams, J. (2007). Matching Objects with Patterns. In ECOOP '07 - Proceedings of the 21st European Conference on Object-Oriented Programming (pp. 273-298). Springer-Verlag.
  • Erwig, M. (1996). Active Patterns. In 8th Int. Workshop on Implementation of Functional Languages, LNCS 1268 (pp. 21-40).
  • García-Caro, A. a. (2018). Fable - The compiler that emits JavaScript you can be proud of! Retrieved from http://fable.io
  • Gordon, M. (2000). From LCF to HOL: a short history. In Proof, language, and interaction (pp. 169-185). MIT Press. Retrieved from https://www.cl.cam.ac.uk/archive/mjcg/papers/HolHistory.pdf
  • Granicz, A. (2018). WebSharper. Retrieved from http://websharper.com
  • Harper, R., Milner, R., & Tofte, M. (1990). The Formal Definition of Standard ML. MIT Press.
  • Kennedy, A., & Syme, D. (2001). Design and Implementation of Generics for the .NET Common Language Runtime. In PLDI 2001 - Proceedings of the ACM SIGPLAN 2001 Conference on Programming Language Design and Implementation. New York: ACM.
  • Leroy, X. (2004). A few papers on Caml. Retrieved from https://caml.inria.fr/about/papers.en.html
  • MacKenzie, D. (2001). Mechanizing Proof - Computing, Risk, and Trust. MIT Press.
  • MacQueen, D. (2015, September 3). The History of Standard ML. Retrieved from http://sml-family.org/history/ML2015-talk.pdf
  • Microsoft. (2012). Key Events in Microsoft History. Retrieved from http://download.microsoft.com/download/7/e/a/7ea5ca8c-4c72-49e9-a694-87ae755e1f58/keyevents.doc
  • Petricek, T., & Syme, D. (2010). Collecting Hollywood's garbage: Avoiding space-leaks in composite events. In ISMM 2010 - Proceedings of International Symposium on Memory Management.
  • Petricek, T., & Syme, D. (2011). Joinads: a retargetable control-flow construct for reactive, parallel and concurrent programming. In PADL 2011 - Proceedings of Practical Aspects of Declarative Languages.
  • Petricek, T., & Syme, D. (2014). The F# Computation Expression Zoo. In PADL 2014 - Proceedings of Practical Aspects of Declarative Languages.
  • Petricek, T., Guerra, G., & Syme, D. (2016). Types from data: Making structured data first-class citizens in F#. In PLDI 2016 - Proceedings of Conference on Programming Language Design and Implementation.
  • Rabhi, F., & Gorlatch, S. (2003). Patterns and Skeletons for Parallel and Distributed Computing. London: Springer-Verlag.
  • Sangiorg, D., & Walker, D. (2001). PI-Calculus: A Theory of Mobile Processes. New York: Cambridge University Press.
  • Seger, C., Jones, R., O'Leary, J., Melham, T., Aagaard, M., Barrett, C., & Syme, D. (2005). An industrially effective environment for formal hardware verification. In IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems, Volume 24, Issue 9 (pp. 1381-1405).
  • Syme, D. (1993). Reasoning with the Formal Definition of Standard ML in HOL. In Higher Order Logic Theorem Proving and Its Applications (pp. 43-60). Springer-Verlag.
  • Syme, D. (1995). A new interface for HOL - Ideas, issues and implementation. In LNCS 971 - Higher Order Logic Theorem Proving and Its Applications pp 324-339. Springer-Verlag.
  • Syme, D. (1999). Declarative theorem proving for operational semantics (PhD thesis). Cambridge. Retrieved from https://www.repository.cam.ac.uk/handle/1810/252967
  • Syme, D. (2004, September 4). F#, GUI Programming and the Problem of Mutually Referential Objects in ML-style Programming . Retrieved from https://github.com/dsyme/fsharp-presentations/blob/master/2004-09-28-serious/dsyme-serious-sep-04-v3.ppt
  • Syme, D. (2006). Initializing Mutually Referential Abstract Objects: The Value Recursion Challenge. Electronic Notes in Theoretical Computer Science (ENTCS), 148(2), 3-25.
  • Syme, D. (2006). Leveraging .NET meta-programming components from F#: integrated queries and interoperable heterogeneous execution. In ML '06 Proceedings of the 2006 workshop on ML (pp. 43-54). New York: ACM.
  • Syme, D., Neverov, G., & Margetson, J. (2007). Extensible Pattern Matching via a Lightweight Language Extension. In ICFP '07 - Proceedings of the 12th ACM SIGPLAN International Conference on Functional Programming (pp. 29-40). ACM.
  • Wadler, P. (1987). Views: A Way for Pattern Matching to Cohabit with Data Abstraction. In POPL '87 - Proceedings of the 14th ACM SIGACT- SIGPLAN Symposium on Principles of Programming Languages (pp. 307-313). New York: ACM.
  • Wadler, P. (1998, August 1998). Why no one uses functional languages. ACM SIGPLAN Notices, 33(8), pp. 23-27.
  • Wlaschin, S. (2017). Domain Modeling Made Functional. Pragmatic Bookshelf.

  1. What is F#, Microsoft Corporation 2018, https://docs.microsoft.com/en-us/dotnet/fsharp/what-is-fsharp 

  2. https://safe-stack.github.io/ 

  3. http://foundation.fsharp.org 

  4. 著者は、小学校の登校中に司書教諭の先生がLogoについて教えてくれたことを思い出しています。1981年のことで、私は10歳でした。プログラミング言語の世界に触れたのはあのときが初めてです。 

  5. 後に、C# プログラマーを指して "Elvis" という語が使われました。 

  6. https://en.wikipedia.org/wiki/HyperCard#History 

  7. https://en.wikipedia.org/wiki/ToolBook 

  8. https://winworldpc.com/product/microsoft-fortran/5x 

  9. 一例(Alves-Foss, 1999) 

  10. 別名「空飛ぶPlamondon兄弟」 

  11. Foundations of Object-Oriented Languages(オブジェクト指向言語の基礎に関するワークショップ), https://conf.researchr.org/series/fool 

  12. Pentium FDIV: The processor bug that shook the world https://www.techradar.com/uk/news/computing-components/processors/pentium-fdivthe-processor-bug-that-shook-the-world-1270773 

  13. 筆者はMirandaに触れたことはありませんでしたが、F# の初期採用者(Ralf Herbrichなど)や、Microsoft社内の支援者(Andrew Blake、2008~2016年のMSRケンブリッジ所長など)は、大学でMirandaに触れたことがあり、よい印象を持っていました。興味深いことに、彼らは理論ドメインから外に出て、機械学習やコンピュータービジョンの分野で活動しており、実用性と生産性の観点からMirandaを高く評価していました。 

  14. A History of OCaml https://ocaml.org/learn/history.html 

  15. 余談ですが、OCamlに熱心だった人たちの中に、後にWikiLeaksで有名になったJulian Assangeがいました。http://caml.inria.fr/pub/mlarchives/caml-list/2000/08/6b8b195b3a25876e0789fe3db770db9f.en.html 

  16. Simple Type Inference for Structural Polymorphism, Jacques Garrigue, 9th FOOL, 2002 http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.9.2521 

  17. .NETにおける "tail." 命令のサポートは、割と長い間、無理やりのパッチ状態で実装されていました:イノベーションであった半面、保守ために継続的に手を入れなければならず、コストがかかっていました。 

  18. https://blogs.msdn.microsoft.com/dsyme/2012/07/05/more-c-net-generics-research-project-history-the-msr-white-paper-from-mid-1999/ 

  19. 当時、Project Lightning(すなわち.NET)は "COM+" と呼ばれていました。VOSとはVirtual Object System(仮想オブジェクトシステム)の略で、当時の.NETオブジェクトシステムのことです。 

  20. How generics were added to .NET http://mattwarren.org/2018/03/02/How-generics-were-added-to-.NET/ 

  21. BillG Review 2001.ppt https://github.com/dsyme/fsharp-presentations/blob/master/generics/BillG%20Review%202001.ppt 

  22. 後のまとめも参照 https://wiki.haskell.org/GHC/FAQ 

  23. https://caml.inria.fr/pub/ml-archives/caml-list/2001/02/5770514eec29b794c2d560fc3282bc14.en.html 

  24. https://caml.inria.fr/pub/ml-archives/caml-list/2001/02/229eebd5314fd127dadb27872f9e4c6f.en.html 

  25. Interestingly, this discussion arose directly in the context of data integration, an area that would drive much of the C# and F# design work in the 2000s. 

  26. Harlequin, Wikipedia https://en.wikipedia.org/wiki/Harlequin_%28software_company%29 

  27. https://caml.inria.fr/pub/ml-archives/caml-list/2001/02/133b91bc1099f414b036a6ded7209d4c.en.html 

  28. https://caml.inria.fr/pub/ml-archives/caml-list/2001/02/5ed4e8db99c99cb983fddea7407f5d9c.en.html 

  29. https://caml.inria.fr/pub/ml-archives/caml-list/2001/02/b67bc40320ae83c25dd035848a767b19.en.html 

  30. https://caml.inria.fr/pub/ml-archives/caml-list/2001/02/394c8e018c81d45cda9c71c20d22518b.en.html 

  31. https://caml.inria.fr/pub/ml-archives/caml-list/2001/03/c505a4570bf94080cb8a7f82b2f3598a.en.html 

  32. The “F” in “F#” comes from both “Functional” and “System F”, an elegant variant of simply typed lambda calculus. The F# community also say “F is for Fun”. 

  33. Internet Archive: http://research.microsoft.com/projects/ilx/fsharp.htm 

  34. https://caml.inria.fr/pub/ml-archives/caml-list/2002/06/8d07fd5058aa26127d1b7e7892698386.en.html 

  35. Internet Archive: http://research.microsoft.com/projects/ilx/fsharp.htm 

  36. This position eventually bore fruit in 2018 when C# 8.0 finally began the transition to assuming non-nullness by default for references types, discussed in the conclusion. 

  37. https://lwn.net/Articles/34678/ 

  38. https://blogs.msdn.microsoft.com/dsyme/2005/01/05/welcome-to-dons-f-blog/. At the time, individual blogging on MSDN was encouraged by management and proved a great way to utilize Microsoft’s positive brand with developers for both the company and many individuals. 

  39. Syme, D., Archeological Semiotics: The Birth of the Pipeline Symbol, 1994, https://blogs.msdn.microsoft.com/dsyme/2011/05/17/archeological-semiotics-the-birth-of-the-pipeline-symbol-1994/ 

  40. Wenzel M., Nipkow T, Paulson L, Isabelle archives, 1994, “added infix op also” and src/Pure/sign.ML#l545 

  41. Surprisingly this feature is yet to make it into any version of C#. 

  42. F# Code I Love, Don Syme, https://skillsmatter.com/skillscasts/11439-keynote-f-sharp-code-i-love 

  43. G'Caml, Caml with Extensional polymorphism extension https://inbox.ocaml.org/caml-list/20010619182424P.Jun.Furuse@inria.fr/ 

  44. http://www.cs.ox.ac.uk/ralf.hinze/WG2.8/ 

  45. https://blogs.msdn.microsoft.com/dsyme/2006/08/15/an-upcoming-experimental-feature-active-patterns-in-f/ 

  46. https://blogs.msdn.microsoft.com/dsyme/2006/03/23/f-first-class-events-simplicity-and-compositionality-in-imperative-reactive-programming/ 

  47. A Brief Introduction to the Reactive Extensions for .NET, Rx https://blogs.msdn.microsoft.com/wesdyer/2009/11/18/a-brief-introduction-to-the-reactive-extensions-for-net-rx/ 

  48. https://en.wikipedia.org/wiki/MLDonkey 

  49. https://en.wikibooks.org/wiki/Haskell/do_notation 

  50. https://www.haskell.org/arrows/syntax.html 

  51. https://blogs.msdn.microsoft.com/dsyme/2007/10/10/introducing-f-asynchronous-workflows/ 

  52. F# meets LINQ, and great things happen (Part I), https://blogs.msdn.microsoft.com/dsyme/2006/01/26/f-meets-linq-and-great-things-happen-part-i/ 

  53. Thesis: Client-side Scripting using Meta-programming http://tomasp.net/blog/webtools-thesis.aspx/ 

  54. https://blogs.msdn.microsoft.com/dsyme/2006/08/23/lightweight-syntax-option-in-f-1-1-12-3/ 

  55. https://blogs.msdn.microsoft.com/dsyme/ 

  56. https://blogs.msdn.microsoft.com/dsyme/2006/09/14/f-on-channel-9/ 

  57. https://blogs.msdn.microsoft.com/dsyme/2006/, https://blogs.msdn.microsoft.com/dsyme/2007/ 

  58. https://blogs.msdn.microsoft.com/dsyme/2006/10/23/f-for-scientists-announced-by-jon-harrop/ 

  59. Composing Reactive GUIs in F# Using WebSharper, Bjornson J., Tayanovskyy A., Granicz A., IFL 2010, https://link.springer.com/chapter/10.1007%2F978-3-642-24276-2_13 

  60. Peake A., Granicz A., The first substantial line of business application in F#, CUFP '09 Proceedings of the 2009 Workshop on Commercial Users of Functional Programming https://dl.acm.org/citation.cfm?id=1668119 

  61. Internet Archive: http://www.intellifactory.com:80/Development.aspx 

  62. https://blogs.msdn.microsoft.com/dsyme/2006/09/06/draft-chapter-2-of-expert-f-essential-language-features/ 

  63. https://blogs.msdn.microsoft.com/dsyme/2007/03/04/f-1-9-almost-ready/ 

  64. Sometimes this gave mixed results: at one presentation a technical assistant of Bill Gates told the author and Ralf Herbrich firmly “you should be focusing on the 250,000 programmers still using Visual Basic 6”. 

  65. Of these, the first adoption succeeded and saw considerable use of F# over multiple years. 

  66. Private email, Thu 30/08/2007 23:34 

  67. At Microsoft in 2008, program managers had broad responsibilities, including product delivery, customer interaction and specification. This was often summarized by saying the PM “represents the customer” to the development organization. 

  68. In retrospect these quant groups likely had other things to worry about in late 2007. On one occasion in New York, when the author asked about the structural problems in the global market, an F# quant said “yes, I should have spotted that” and added that he felt “personally responsible” for the GFC. A rare admission from the finance sector. 

  69. Microsoft’s Experiments with Software Transactional Memory Have Ended https://www.infoq.com/news/2010/05/STM-Dropped 

  70. theregister.co.uk: Microsoft cuts loose Iron languages 

  71. Microsoft drops Dryad; puts its big-data bets on Hadoop https://www.zdnet.com/article/microsoft-drops-dryad-puts-its-big-data-bets-on-hadoop/ 

  72. Microsoft to close Microsoft Research lab in Silicon Valley https://www.zdnet.com/article/microsoft-to-close-microsoft-research-lab-in-silicon-valley/ 

  73. https://blogs.msdn.microsoft.com/somasegar/2007/10/17/f-a-functional-programming-language/ 

  74. Syme, D., December 2006. Blog post. F# helps show we’re not Neanderthals. https://blogs.msdn.microsoft.com/dsyme/2006/12/05/f-helps-show-were-not-neanderthals/

  75. It was finally de-emphasized around 2015 once F# developed as an open source, cross-platform language with a strong web and cloud programming story. F# today is for programming of all kinds. 

  76. https://fsharp.org/specs/language-spec/ 

  77. This day is celebrated as “F# Day” in the F# community. https://fsharpforfunandprofit.com/posts/happy-fsharp-day/ 

  78. Programming Languages and Dimensions http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.93.807 

  79. The F# September 2008 CTP is now available! https://blogs.msdn.microsoft.com/dsyme/2008/08/29/the-f-september-2008-ctp-is-now-available/ 

  80. The name is courtesy of Chris Smith 

  81. Freebase: a collaboratively created graph database for structuring human knowledge. https://dl.acm.org/citation.cfm?id=1376746 

  82. Ross McKinlay is also famous in the F# community for humorous applications of F# type providers including encoding “choose your own adventure” games in the autocomplete-menus made available to the programmer via the compile-time meta-programming machinery that integrates with the IDE. http://www.pinksquirrellabs.com/post/2013/07/29/Choose-Your-Own-Adventure-Type-Provider.aspx 

  83. Announcing the F# Compiler + Library Source Code Drop https://blogs.msdn.microsoft.com/dsyme/2010/11/04/announcing-the-f-compiler-library-source-code-drop/ 

  84. Facilitating Open Contributions for the F# Compiler, Library and Visual F# Tools https://blogs.msdn.microsoft.com/fsharpteam/2014/04/03/facilitating-open-contributions-for-the-f-compiler-library-and-visual-f-tools/ 

  85. F# Language Design RFCs https://github.com/fsharp/fslang-design/ 

  86. F# Compiler Services http://fsharp.github.io/FSharp.Compiler.Service/ 

  87. Ionide - A Visual Studio Code package suite for cross platform F# development. http://ionide.io/ 

  88. Paket: a dependency manager for .NET - https://fsprojects.github.io/Paket/ 

  89. F# Make: a DSL for Build Tasks and more - https://fake.build/ 

  90. http://community.fsharp.org/user_groups 

  91. http://fsharp.org/testimonials 

  92. http://stationq.github.io/Liquid/ 

  93. Apple WWDC 2014 - Swift Introduction https://www.youtube.com/watch?v=MO7Ta0DvEWA 

  94. Why you should use F#, Mads Torgersen and Phillip Carter, Microsoft https://channel9.msdn.com/Events/Build/2017/T6064 

  95. The language designs of Java, C++, JavaScript and Python all progressed during this time, but to a lesser extent than C#. 

  96. https://en.wikipedia.org/wiki/Axum_(programming_language

  97. http://joeduffyblog.com/2015/11/03/blogging-about-midori/ 

  98. https://blogs.msdn.microsoft.com/dsyme/2006/03/23/f-first-class-events-simplicity-and-compositionality-in-imperative-reactive-programming/ 

  99. Scala macros: let our powers combine! On how rich syntax and static types work with metaprogramming. Eugene Burmako, SCALA@ECOOP 2013 https://www.semanticscholar.org/paper/Scala-macros%3A-let-our-powers-combine!%3A-on-how-rich-Burmako/34ac77d1b2646c9a48c519d91e90b584296f833c 

  100. https://graydon.livejournal.com/256533.html 

  101. https://hackernoon.com/the-first-typescript-demo-905ea095a70f 

  102. The F# community joke being “Question: What can C# do that F# can’t?” “Answer: NullReferenceException!” 

  103. Null References: The Billion Dollar Mistake, Tony Hoare, https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare 

  104. Don Syme, Tomas Petricek and Dmitry Lomov, The F# Asynchronous Programming Model, PADL 2011, http://tomasp.net/academic/papers/async/ 

  105. The history of async programming, continuations and co-routines would need to be the subject of a different article, stretching back to LISP. C# 5.0 added new elements to the design of “async/await” suitable for an ALGOL language, including state-machine compilation, derived originally from the Axum prototype. In this light, F# async was a predecessor to C# async/await, though the latter was not a copy of the former. 

  106. https://github.com/fsharp/fslang-suggestions/ 


Last Update: 2019-02-12 05:26:08