我只是想知道如何编写用户定义的平方根函数 (sqrt),使其与 F# 的单位系统正确交互。
它应该是什么样子:
让 sqrt (x : float<'u ^ 2>) = let x' = x / 1.0<'u ^ 2> // 删除单元 (x ** 0.5) * 1.0<'u> // 重新分配单元
但这是不允许的,因为不允许非零常量具有通用单位。
有没有办法写这个函数?使用内置sqrt
它可以正常工作,那么它有什么魔力呢?
我只是想知道如何编写用户定义的平方根函数 (sqrt),使其与 F# 的单位系统正确交互。
它应该是什么样子:
让 sqrt (x : float<'u ^ 2>) = let x' = x / 1.0<'u ^ 2> // 删除单元 (x ** 0.5) * 1.0<'u> // 重新分配单元
但这是不允许的,因为不允许非零常量具有通用单位。
有没有办法写这个函数?使用内置sqrt
它可以正常工作,那么它有什么魔力呢?
允许非零泛型常量很容易破坏单元类型系统的安全性(参见 Andrew Kennedy 的论文)。我相信您最后一个问题的答案sqrt
在某种意义上确实很神奇,因为不可能通过正常方式定义具有该类型签名的参数函数。但是,可以通过利用装箱和强制转换来做您想做的事情(至少在当前版本的 F# 中):
let sqrt (x : float<'u^2>) =
let x' = (float x) ** 0.5 (* delete unit and calculate sqrt *)
((box x') :?> float<'u>)
@kvb 是对的,更一般地说:
如果你有一个非单元感知算法(例如,你写了'cube root'),并且你想在上面放置单元,你可以将算法包装在一个具有正确类型签名的函数中,并使用例如“float”来'当他们进来时抛弃”这些单位,并在退出时“添加”适当的单位。
在 RTM 版本(Beta2 之后)中,F# 将具有用于“添加回单元”的原始库函数,因为 box-and-downcast 方法目前是一种破解语言/库中缺乏这些原始函数的方法.