F#的计量单位

从各个意义上,都可以说计量单位很重要。度量衡的统一是社会化大生产和市场交换的基石。这句正确的废话跟F#没有半毛钱的关系,直到我看帮助看到了这个:

[<Measure>] type m
let l = 1<m>

脑袋顿时秃起来哦不兴奋起来。仔细看了看几个帖子,发现这个东西是F#的一个特性,叫做Units of Measure。

其实网上提的不太多,本来F#的内容就少。

  • 比较高访问量的:F# Units of Measure
  • Wikibooks上的:F Sharp/Units of Measure
  • 一个停更很久的小伙子“要你命3000”:BrendoTRON3000’s Programming Blog有两个帖子。

为什么需要这个计量单位

这个特性看起来很美好,编程序的时候能够把单位写在变量的后面,可以自动检查单位的正确性,比如:

// open FSharp.Data.UnitSystems.SI.UnitSymbols
// 或者自己定义下:
[<Measure>] type m
[<Measure>] type s
let speed = 10<m/s>
let time = 5<s>
let distance = speed * time

这里距离自动推导出距离的单位m,而且speed * time的结果也是m,如果写成speed + time就会报错,因为单位不匹配。

好多帖子里面还提到NASA把单位搞错,导致火箭坠毁,这个我没仔细去找相关的资料。不过老美那个没文化的,全球都在搞国际单位制,就他抱着英制不放,看NACA(NASA早期的名字)的文章简直是费了劲。

只是这个单位写法和用法,都是编译期的,在运行期间,这个单位就没有了。没有办法访问,没有办法转字符串,没有办法获取和判断。唯一的用处就是在编译时候检查单位的正确性。

这么好的奇淫巧技,微软到底是怎么让它进入F#的呢?我思考了非常久,也没有想明白。因为这个东西这么好的话,C/C++/Java肯定早就要搞起来了啊?为什么呢?

为什么C/C++/Java没有这个计量单位的功能

我想了很久,也没有想明白。我觉得可能是因为这个东西太复杂了,而且用处不大。比如我写了一个函数:

let f (x:float) = x + 1.0

这个函数的输入是float,输出也是float,那么我在调用的时候,就不需要写f 1.0f,因为编译器会自动推导出来。如果我写成:

let f (x:float<m>) = x + 1.0<m>

有两种可能:

  1. 通过命名约定、检查工具、单元测试,不管是什么东西,在别的主流工程语言中,这个问题不复存在。所以这个功能就没有必要了。
  2. 这个功能实现起来跟人类实现度量衡统一一样难,最聪明的物理学家,到现在连功的单位都没有统一,简直是人类之耻。
  3. F#做这个功能实在是太简单?所以语言实现的胸弟随便就做上了?

为了开心和不开心,我还是把跟这个相关的东西都看了一遍,头发少了好几根。

真正有用的Unit of Measure

说这个玩意没有用是一方面,说计量单位没有用那就是胡扯。有一个很好的包叫做CoolProp,可以计算各种物质的物理性质,比如下面的代码输入是温度和压力,输出是密度。这个密度的单位是kg/m^3

let water = CoolProp.PropsSI("D","T",300.0,"P",101325.0,"Water")

这个包C++编的,提供了.NET接口,叫做SharpProp,用F#可以直接调用。

let water = SharpProp.PropsSI("D","T",300.0,"P",101325.0,"Water")

这么下起来是不是很没有牌面?

.NET程序员(准确地说是C#程序员)大神,做了一个很有用的单位系统。这个东西叫做UnitsNet。这个东西是用C#写的,但是F#也可以直接调用。

open System
open SharpProp
open UnitsNet.Units
open UnitsNet.NumberExtensions.NumberToPressure
open UnitsNet.NumberExtensions.NumberToTemperature
open UnitsNetlet fluid (f: FluidsList) (p: float) (T: float) =(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins()))type Fluid withmember this.density = this.Density.KilogramsPerCubicMetermember this.pressure = this.Pressure.Pascalsmember this.temperature = this.Temperature.Kelvinsmember this.specificHeat = this.SpecificHeat.JoulesPerKilogramKelvinmember this.viscosity =match this.DynamicViscosity with| v when v.HasValue -> v.Value.NewtonSecondsPerMeterSquared| _ -> Double.NaNmember this.kinematicViscosity =match this.KinematicViscosity with| v when v.HasValue -> v.Value.SquareMetersPerSecond| _ -> Double.NaNlet density (f: FluidsList) (p: float) (T: float) =(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).Density.KilogramsPerCubicMeterlet specificHeat (f: FluidsList) (p: float) (T: float) =(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).SpecificHeat.JoulesPerKilogramKelvinlet viscosity (f: FluidsList) (p: float) (T: float) =match(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).DynamicViscositywith| v when v.HasValue -> v.Value.NewtonSecondsPerMeterSquared| _ -> Double.NaNlet kinematicViscosity (f: FluidsList) (p: float) (T: float) =match(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).KinematicViscositywith| v when v.HasValue -> v.Value.SquareMetersPerSecond| _ -> Double.NaN[<EntryPoint>]
let main argv =for T in 280..10..350 dolet water = fluid FluidsList.Water 101325.0 (float T)printfn$"%20f{water.density} kg/m³%20f{water.pressure} Pa%20f{water.temperature} K%20e{water.viscosity} Pa·s%20e{water.kinematicViscosity} m²/s%20f{water.specificHeat} J/kg·K"printfn ""for T in 280..10..500 dolet air = fluid FluidsList.Air 101325.0 (float T)printfn$"%20f{air.density} kg/m³%20f{air.pressure} Pa%20f{air.temperature} K%20e{air.viscosity} Pa·s%20e{air.kinematicViscosity} m²/s%20f{air.specificHeat} J/kg·K"0 // return an integer exit code

很简单的就能把各个单位在运行期的行为都统一起来。这个东西是真正有用的。

UnitsNet的功能举例

UnitsNet把一个带单位的量描述为(数值,单位)的组合,不同的单位之间的转换都在运行时可以获得,各单位的名称也都是在运行时可以获得的。这个东西的功能非常强大,可以用来做各种单位转换,比如下面的代码就是把压力从帕斯卡转换为其他单位。

open UnitsNet
open UnitsNet.Units
open UnitsNet.NumberExtensions.NumberToPressure
// 用不同的单位定义一个量
let p = 101325.0.Pascals()
let p1 = 1.0.Atmospheres()
let p2 = 760.0.Torr()
let p3 = 14.695948775513.PoundsForcePerSquareInch()
let p4 = 1013.25.Millibars()
let p5 = 1013.25.Hectopascals()
// 把一个量转化为不同的单位
printfn $"%f" p.Atmospheres
printfn $"%f" p.Torr
printfn $"%f" p.PoundsForcePerSquareInch

总结

  1. F#的Unit of Measure是一个很有意思的功能,但是实际上没有什么用。
  2. UnitsNet实现的单位系统是真正有用的。
  3. F#调用C#的库还是很好很强大的。

F#奇妙游(8):计量单位相关推荐

  1. F#奇妙游(6):如何不用for循环以及循环

    For循环 在F#中,for循环的语法如下: for <identifier> = <start> to <end> do<body> 但是所有函数式编 ...

  2. F#中有趣的计量单位

    "失足"的NASA气象卫星 1998年2月,美国宇航局(NASA)发射了一枚探测火星气象的卫星,预定于1999年9月23日抵达火星.然而研究人员惊讶地发现,卫星没有进入预定的轨道, ...

  3. 阿里文娱旗下优酷联合河南卫视推出2022“元宵奇妙游”,创新传承传统文化

    随着中国经济的发展,中华民族越来越自信,国潮风愈演愈烈,中华文化带有典型的中国特色,如今国潮已经悄悄席卷各大行业,中国元素已经成为人们追逐的对象.文化产业亦是如此,河南卫视宣扬民族文化,在各大卫视中脱 ...

  4. INTRODUCING F#

    第一篇,从零开始编写我们的第一个F#程序. 什么是F#,我为何要学它? F#是一种.NET平台上的函数式编程语言.就像C#和VB.NET,F#可以利用.NET的核心类库,如WPF,WCF,VSTO等等 ...

  5. 95后热搜哪些事,夸克用AI引擎发布2021年度关键词

    编辑 | 宋慧 出品 | CSDN 云计算 岁末将至,哪些心潮澎湃的瞬间与难以忘怀的言语,能够代表你的2021? 12月14日,在夸克''Meet AI''开放日上,阿里巴巴智能信息事业群旗下的智能搜 ...

  6. 坚定文化新自信 提升文化软实力

    <坚定文化新自信 提升文化软实力> 党的十九大报告指出,文化是一个国家.一个民族的灵魂.文化兴国运兴,文化强民族强.文化是人类文明的精华,是时代发展的荟萃,是社会创造力的源泉,是国际地位软 ...

  7. 迪士尼超级计算机多少钱,上海迪士尼乐园公布票务调整方案,明年1月9日起实行新票价...

    原标题:上海迪士尼乐园公布票务调整方案,明年1月9日起实行新票价 上海迪士尼度假区今天公布票务调整方案,新方案将于2022年1月9日起实行.届时,上海迪士尼度假区将在现行四级票价结构下调整门票价格,各 ...

  8. 阿里大文娱让中国传统文化融入年轻人的生活

    2021年10月,阿里大文娱旗下优酷和河南广电达成战略合作,双方合作,推出了多台中国风晚会. 早在2020年,阿里大文娱联合阿里创新事业群,推出了青年文娱消费大数据报告,这份报告显示,中国的流行音乐相 ...

  9. Python 之 小白爬虫

    设置环境 import requests from lxml import etree #lxml解析库的etree方法 爬取微博热搜榜 url = 'https://s.weibo.com/top/ ...

最新文章

  1. nginx配置http、https访问,nginx指定ssl证书,阿里云腾讯云华为云设置nginx https安全访问
  2. springboot 自动装配_Spring Boot 自动装配流程
  3. MySQL最高每秒57万写入,带你装X,带你飞!
  4. 推荐六款帮助你实现惊艳视差滚动效果的 jQuery 插件
  5. SQL Server timeout分析和总结
  6. 程序员如何在百忙中更有效地利用时间,如何不走岔路,不白忙(忙得要有效率,要有收获)...
  7. [Asp.net MVC]HandleErrorAttribute异常过滤器
  8. quicksearch连接oracle,dos命令下连接oracle数据库表
  9. Python设计模式:建造者模式
  10. 网易云音乐数仓建模实践
  11. 自我成长与团队管理——一些总结
  12. c++语言生成一个随机数,C++ 快速随机数生成器
  13. Fiddler+手机模拟器+java采集抖音评论数据
  14. iOS-打开本地或下载的Excel文件
  15. Android熄屏与亮屏控制
  16. TK 设置tkinter窗口的置顶属性,保持最上层
  17. Win11新加硬盘不显示的解决方法
  18. 亲爱的老狼-display的应用
  19. windows10使用cuda11搭建pytorch深度学习框架——运行Dlinknet提取道路(二)——代码运行问题解决
  20. 阿里云开发者大会正式启动

热门文章

  1. cdn 引入的资源需要通过 externals 排除打包哦~
  2. 部分常见ORACLE面试题以及SQL注意事项
  3. UE4武器绑定--将武器模型绑定到人物身上、
  4. 国内各大厂ChatGPT技术布局及应用场景
  5. 图论——邻接矩阵之无向网
  6. 有趣又有料:任意操控静态图片中人的眼球
  7. 增广贤文--中华蒙学经典
  8. 微信跳转外部浏览器直接下载app的实现方式
  9. OSPF网络中两端设备网络类型不一致所带来的故障现象
  10. Android Studio lint工具所提示的需要注意的内容简要记录