p_tan's blog

勉強日記です。ツッコミ大歓迎

なぜC#ではなくF#を使いたいのか : 構造化分析と関数型プログラミング #fsharp

この記事は F# Advent Calendar 2017 - Qiita の 11 日目の記事です。

本記事では、なぜ自分がC#ではなくF#を使いたいのかを記したいと思います。

この記事で言いたいこと

  • コンピュータシステムの本質とは入力データを出力データに変換することだと思っているので、そのままシンプルにデータフローでモデリングしたいよ
  • 関数型プログラミングとDFDは相性が良いよ
  • DFDのデータ・ディクショナリは代数的データ型(F#ではレコードや判別共用体)でそのままコードに落とし込めるよ
  • だからC#よりもF#を使いたいよ

コンピュータシステムとは何をするものか

我々ソフトウェアエンジニアは入力データを出力データへ変換するためにソフトウェアを作っています。

入力データは、UI越しのユーザ入力かもしれないし、ファイルから読み取るのかもしれないし、ネットワーク越しにくるのかもしれないし、OSのタイマーが一定間隔で発行するイベントかもしれません。

出力データは、UIでのユーザへの情報提示かもしれないし、ファイル、ネットワークなどへ送り出すのかもしれません。

つまり、ソフトウェアシステムとは、入力データを出力データに変換するプロセスです。そして、そのためのモデリングツールとして、何十年も前からあるのが構造化分析とデータフローダイアグラム(DFD)[1]です。

なお、近年では、リアクティブプログラミング用のライブラリ(Rxなど)によって、時系列の一連の入力データを、これまた時系列の出力データに変換するプロセスも宣言的に書けるようになってきています[2][3]。

関数型モデリングツールとしてのDFD

オブジェクト指向分析におけるモデリングツールとしてUMLがあります。では、関数型プログラミングにおいてモデリングに使うツールは何でしょうか。 関数型プログラミングでは、基本的に副作用のない関数を組み合わせてアプリケーションを作成します。副作用のない関数は入力を出力に変換するものなのでDFDと相性がよく、関数型プログラミング言語ではDFDをそのままコードに落とし込む事ができます。

データ・ディクショナリと代数的データ型

構造化分析とシステム仕様[1] によると、DFDでフロー中を流れるデータはデータ・ディクショナリに定義されます。そして、個々のデータは、要素の繰り返し・連結・選択によって定義されます。

名前 = 姓 and 名
分類 = 幼児 or 子供 or 大人

この構造は、そのまま代数的データ型(F#では判別共用体やレコード)で表す事ができます。

type 名前 = { 姓 : string; 名 : string }
type 分類 = 幼児 | 子供 | 大人

DFDをコードに落とし込む際の、C#と比較したF#の利点

以前の記事 なぜC#よりもF#なのか 2017 #fsharp - p_tan's blog でもC#とF#を比較していますが、DFDをコードに落とし込むという観点からC#とF#を比較すると、F#には以下のようなメリットがあります

  • ユーザ定義型を作成するのが簡単
  • 粒度の細かな関数を組み合わせて大きな関数を作りやすい。すなわち、DFDのプロセスの分解と、関数の粒度を合わせやすい
  • 上記の代数的データ型によって、データ・ディクショナリのコード化が楽
  • パターンマッチでの網羅性判定により、機能追加時の実装忘れなども警告が出る

まとめ

関数型プログラミングは、「普通の」アプリケーションの開発をきっとシンプルにしてくれます。

業務でF#つかいたいなぁ・・・。

参考書籍