我读过这篇MSDN文章:
...单位类型是指示缺少特定类型的类型 值;单位类型只有一个值,作为一个 占位符,当没有其他值存在或需要时...... 单元类型类似于C#和C ++等语言中的void类型。
所以......好吧,我明白,单位类型就是这样一种类型,它只有一个值()
。但我有一些问题:
我不明白为什么不在F#中使用void类型,比如C#和C ++使用。
如果我查看下表:
Type .NET Type Description
void Void Indicates no type or value.
我看到F#确实有一个void类型。所以我不明白为什么需要单位类型;看起来它与void非常相似。
我认为它与功能语言范式有关,这就是为什么需要它,所以请...向我解释一下这个问题。
答案 0 :(得分:13)
在C#中,没有可以用作参数类型的void
类型的值。此外,void
不能用作泛型类型参数(例如,C#需要使用并行Func<...>
和Action<...>
委托类型,但F#只需要一个函数类型{{ 1}}可以抽象两个)。在许多情况下,这最终大大简化了F#编程;例如,执行一些副作用但不返回值的... -> ...
动作是Async
类型的实例,但在C#中无法创建相应的Async<unit>
或其他
答案 1 :(得分:8)
请参阅维基百科的Unit Type
无效类型为单位类型
在C,C ++,C#和Java中,void表示空类型。单位类型 在C中将是struct {},但C禁止空结构 语言规范。相反,void以某种方式使用 模拟单元类型的一些但不是全部的属性,如 详情如下。
调用约定的区别
真实单位类型与虚空之间的第一个显着差异 type是单元类型可能始终是a的参数类型 函数,但void类型不能是C中参数的类型, 尽管它可能看起来是列表中的唯一参数。
存储差异
第二个值得注意的区别是空洞类型是空的 永远不会存储在记录类型中,即在结构或类中 C / C ++。相反,单位类型可以存储在记录中 函数式编程语言,即它可以表现为a的类型 领域;上面用C ++实现的单元类型也可以 存储。虽然这似乎是一个无用的功能,但它确实允许一个 实例,优雅地将集合实现为单元类型的映射;在 如果没有单位类型,人们仍然可以通过这种方式实现集合 为每个密钥存储一些其他类型的虚拟值。
答案 2 :(得分:4)
另一种看待它的方法是将()视觉化为一个arity为0的元组。
鉴于()用于分隔元组,我们得到
(abc, def, xyx) a tuple with arity of 3
(abc, def) a tuple with arity of 2
(abc) a tuple with arity of 1, which can be reduced to abc
() a tuple with arity of 0, called unit
在基于lambda演算的函数式语言中,函数接受单个参数并返回单个值。 currying支持多个参数。参数和返回值也可以是元组以支持多个值。
我对unit /()的解释是没有值,表示为元组。
答案 3 :(得分:1)
本文解释了 void
的一些限制以及为什么您甚至可能希望在 C# 中使用 Unit
:https://chtenb.dev/?page=unit-cs
最重要的是,您不能将 void
用作泛型类型中的类型参数,例如 Task<void>
。使用单位类型代替 void 可以解决这个问题。
这是本文中使用的 Unit 实现。
public struct Unit : IEquatable<Unit>
{
public static readonly Unit unit;
public override bool Equals(object obj) => obj is Unit;
public override int GetHashCode() => 0;
public static bool operator ==(Unit left, Unit right) => left.Equals(right);
public static bool operator !=(Unit left, Unit right) => !(left == right);
public bool Equals(Unit other) => true;
public override string ToString() => "()";
}