F# 函数式编程之 – unpacking/deconstruct

  • A+
所属分类:.NET技术
摘要

原文 https://fsharpforfunandprofit.com/posts/overview-of-types-in-fsharp/这个特性我觉得也比较新鲜,以前没有见过,先看代码吧:

原文 https://fsharpforfunandprofit.com/posts/overview-of-types-in-fsharp/

这个特性我觉得也比较新鲜,以前没有见过,先看代码吧:

type Dollar = Dollar of int let earn d:Dollar = d + 10 // Error 

虽然只有两行代码,但有不少值得说明的地方。

第一行,有两个 Dollar, 但它们有不同的含义,也只能用在不同的地方。第一个 Dollar 是一个类型,而第二个 Dollar 不是类型而是 union case, 这里只是故意重名,以便在两种场合都能使用 Dollar 这个单词。

因此,第二行代码里的 Dollar 是类型,此时,第二行会报错,因为类型 Dollar 不能与类型 int 直接相加。

我们把其中一个 Dollar 改成别的单词,就可以看得更清楚:

type Money = Dollar of int let earn d:Dollar = d + 10  // Error 

这样,由于第一个 Dollar 已经改成 Money, 因此 Dollar 再也不能当作类型来使用,第二行会报错,而这次的错误原因是 “Dollar 不是类型”。

再看下面的代码:

// single case union type Dollar = Dollar of int let earn (Dollar d) = d + 10 // OK 

上面的代码,第二行,就用到了我说的新鲜特性,这里的 Dollar 不是类型,而是 union case, 同时,由于 union case 可以用于 pattern match, 根据 pattern match 的原理,(Dollar d) 正是一个 pattern, 即 (Dollar int), 因此,d 的类型就是 int.

由于 d 的类型是 int, 因此可以与 10 相加,这次代码不会报错。

值得一提的是,这里发生 pattern match 的地方是一个函数的参数!

更神奇的是,这里 (Dollar int) 同时兼具两个作用:

  1. 限定了该参数的类型是 Dollar, 如果输入一个 int 或别的类型,会报错,从而确保了类型安全。

  2. unpacking/deconstruct, “顺便” 从这个参数里把 Dollar 的内涵数据 int 给解构出来了。

本文介绍了 F# 的一个有趣的特性(unpacking/deconstruct), 该特性表面上看着简单,背后却涉及 type 与 union case 的区别,以及 pattern match 的用法。