12 F# 2.0 -- 測定単位
2021-09-25 00:00:21
2009年に1つの重要な機能が言語に追加されました。測定単位のチェックと推論です。 この研究はAndrew Kennedyによって開始されました。MSR Cambridgeの研究者で、その博士論文はHindley-Milner型推論と単位の推論を統合する方法を示すものでした[Kennedy 1995]。 2007年後半、Kennedyはプロトタイプを作成し始め、2007年12月10日に作業中バージョンへのリンクが社内に送られました。 プロトタイプは翌年まで洗練され、2008年8月29日にプレビューリリースで公開されました[Syme [n.d.]a]。 単位の推論を追加することは、Microsoft TCIの文脈では他の目標に沿ったものでしたし、 そしてそれは、他の言語では未だ実現されていない、優雅で強力かつ邪魔にならない機能でもありました。
この機能の概要として、次の定義を考えます。
[<Measure>] type cm
[<Measure>] type ml = cm^3
[<Measure>] type L
let convert_ml_l (x : float<ml>) = x / 1000.0<ml/L>
このコードは、2つの新しい単位( cm
および L
)と1つの単位略語( ml
)を宣言しています。
変換関数は、ml
と L
の間の変換を定義します。
実際には、SI単位系を定義したライブラリーがF# の標準ライブラリーで提供されます。
単位に関してジェネリックなコードもサポートされています。
// 距離、単位はメートル
[<Measure>] type m
// 時間、単位は秒
[<Measure>] type s
let genericSumUnits (x: float<'u>) (y: float<'u>) = x + y
let v1 = 3.1<m/s>
let v2 = 2.7<m/s>
let x1 = 1.2<m>
let t1 = 1.0<s>
let result1 = genericSumUnits v1 v2 // 正しい関数呼び出し
let result2 = genericSumUnits v1 x1 // エラー報告:単位の不一致
新しいデータ構造も、単位に関してジェネリックにすることができます。
type vector3D<[<Measure>] 'u> =
{ x : float<'u>
y : float<'u>
z : float<'u>}
// 位置ベクトルの作成
let xvec = { x = 0.0<m>; y = 0.0<m>; z = 0.0<m> }
// 速度ベクトルの作成
let v1vec = { x = 1.0<m/s>; y = -1.0<m/s>; z = 0.0<m/s> }
技術的な観点から見ると、測定単位機能の主な挑戦は、F# 版のHindley-Milner型推論との統合です[Kennedy 2009]。