空括号() 是所谓的unit 类型,即只能有一个值的类型。具有至少一项的元组类型可以具有任意数量的值(例如,定义为一个 Int 的元组的类型可以具有无限数量的值,从 (-∞) 到 (+∞))。但是“空元组”的可能值有多少?只有一个,因此它被称为 unit 类型。
单位类型的价值在于你可以在其他语言有null或void类型的地方使用它,同时避免null带来的问题。例如,正如您所注意到的,它通常用于您想说“我不在乎价值是什么”的地方。 但是那里是有价值的;这不是没有价值。
这有很多好处;例如,您可以说“ALL 函数返回一个值”,这将是正确的。有时值是您不关心的值,但 所有 函数都会返回一个值。在具有void 类型的语言中,您不能这么说。例如,C# 有两种不同的方式来声明函数委托:Func<T> 用于返回类型为 T 的函数,Action 用于返回 void 的函数。在 Elm(和 F#,以及其他使用单位类型的函数式语言)中,不需要这种区别:所有函数都返回一个值,因此所有函数都可以被视为等同于 Func<T>。有时类型 T 是空元组,但这意味着您不必编写两个版本,例如 map。
另一个优点是它可以让您更轻松地组合函数。这是取自the Wikipedia page on unit types 的示例。在 C 中,你不能这样做:
void f(void) {}
void g(void) {}
int main(void)
{
f(g()); // compile-time error here
return 0;
}
这是一个错误,因为您不能将void 作为参数传递:这是一个值的缺失。这意味着您不能使用标准函数组合将函数 f 和 g 链接在一起。但这里是同一篇文章中的另一个 sn-p,这次是 C++,展示了如果你给 C++ 一个类似 Elm 的单元类型会是什么样子:
class unit_type {};
const unit_type the_unit;
unit_type f(unit_type) { return the_unit; }
unit_type g(unit_type) { return the_unit; }
int main()
{
f(g(the_unit));
return 0;
}
现在,因为g 返回一个真实值(即使它是您不关心的值),您可以有意义地组合f 和g。从长远来看,这会使您的程序更加优雅和易于阅读。
一些可能对您有所帮助的进一步阅读:
-
https://en.wikipedia.org/wiki/Unit_type(我已经在这个答案中链接过一次)
- Why do I need to use the unit type in F# if it supports the void type?
希望这会有所帮助!