动态

详情 返回 返回

小眾語言的巧思:F#為基礎類型添加了單位 - 动态 详情

在 F# 中,單位類型(Units of Measure) 是一種用於在類型層面標註物理單位的語言特性,能夠顯著提升代碼的安全性可讀性

這項特性的核心優勢在於能夠防止物理單位混用引發的錯誤,例如:

  • 不小心將“千克”和“斤”混用
  • NASA 火星氣候軌道器的災難性事故:混淆了英制單位(磅力)和公制單位(牛頓),導致經過近 10 個月的長途跋涉後,上億美元的探測器在接近火星時解體
  • 加拿大航空著名的“吉姆利滑翔機”事件:飛機的系統按公斤計算燃油,而地勤人員卻以為單位加油,結果飛機只加了一半燃料,不得不在空中滑翔迫降

在多數編程語言中,物理單位往往只能通過變量命名、註釋或開發規範來維持一致性,編譯器無法自動檢查單位是否匹配。而一些語言雖然也能通過複雜的模式來模擬單位系統,例如:

  • Go 使用類型別名
  • Rust 藉助 New Type 與操作符重載
  • C++ 結合強類型定義、自定義字面量和操作符重載

但這些方法都不夠簡潔直觀。

F# 的單位類型特性則提供了一種新寫法,來避免單位混用問題:只要在整數、浮點數這些基礎類型的值上標註了單位,編譯器就會在執行不合理的計算(比如“1 米 + 1 英尺”)時提前報錯,將 bug 扼殺在編譯期。

下面,我們將以一個“華氏温度轉換為攝氏温度”的簡單示例,來領略一下 F# 中單位類型的魅力。

[<Measure>]
type C // 定義一個“單位”:C 表示攝氏度(Celsius/Centigrade)

[<Measure>]
type F // 定義另一個“單位”:F 表示華氏度(Fahrenheit)

// FtoC 函數:把帶單位的華氏温度 float<F> 轉換為攝氏温度 float<C>
let FtoC (temp: float<F>) : float<C> =
    // 華氏轉攝氏公式: (F - 32) × 5/9
    // 注意:我們使用 32.0<F> 表示數值 32,單位是華氏度
    // 1.0<C / F> 是轉換結果的單位:從 F 到 C
    5.0 / 9.0 * (temp - 32.0<F>) * 1.0<C / F>

// toF 函數:將一個普通的 float 數值轉為帶單位的 float<F>
let toF (temp: float) : float<F> = temp * 1.0<F>

// 示例變量 x 是一個普通浮點數,代表華氏温度 100°F
let x = 100.0

// 把 x 轉為帶單位的 float<F>  → 調用 FtoC 轉為攝氏度 → 除以 1.0<C> 去掉單位用於顯示
printfn "%.2f°F = %.2f°C" x (FtoC(toF x) / 1.0<C>)

運行結果

100.00°F = 37.78°C

在代碼中標註物理單位,乍看之下或許只是“錦上添花”。但當你目睹單位混用如何導致探測器解體、飛機迫降、算法出錯時,就會明白——寫在文檔裏的“規範.pdf”,無論如何加強管理培訓,只要不能通過編譯器化身為“規範.exe”,就等於形同虛設

🔚

user avatar whaosoft143 头像 momodel 头像 tizuqiudexiangpica 头像 qiyuxuanangdelvdou 头像
点赞 4 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.