matarillo.com

The best days are ahead of us.

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 )を宣言しています。 変換関数は、mlL の間の変換を定義します。 実際には、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]。


インデックスへ戻る