9

编辑:Void我的意思是 Haskell 的Void类型,即不能有值但是的空类型undefined

关于 Swift Evolution 是否将noreturn函数属性替换为实际Void类型的讨论正在进行中。为此,我们必须确保这将为平台带来真正的好处。使用Void作为返回类型是不够的。

所以我要求你提供非常实用的例子,其中的使用Void增加了代码的清晰度、简洁性和通用性。也许它会使用类(在 Haskell 意义上),也许是泛型,也许它会合并Void到 ADT 中。

但是,不要对 HKT、Monads 和所有高级别的东西走得太远。标准库中的实用函数也是一个不好的例子。一个完美的例子是街机游戏或类似游戏的一部分。

4

1 回答 1

16

(说是没有Void值的类型,不同于只有一个值的类型,通常称为Unit。)

在 Haskell 流式库(如流式管道)中,有一些数据类型表示“类型值的来源a,一旦用尽,就会返回类型值r”。类似的东西Producer a m r(Them是一个基本的单子,但在这里不相关。)

让生产者返回一个值(与他们在运行时发出的值类型无关的类型)实际上非常有用。例如,您可以将“流式拆分器”定义为具有以下类型的函数:

streamingSplit :: Producer a m r -> Producer a m (Producer a m r)

此函数对生产者进行分段,而不必在内存中累积拆分之前的所有元素。

现在,如果我们想在类型级别表达生产者永远不会停止生产东西怎么办?我们可以让它返回一个类型的值Void,比如Producer a m Void.

另一个可能的用例。假设您有一个接受可能失败的回调的高阶函数。就像是:

-- does something with the wrapped callback, maybe emit a log message or whatever
takesACallback :: (a -> IO (Either e r)) -> a -> IO (Either e r)

如果我们想定义一个永远不会失败的for函数takesACallback版本怎么办?进出是一件麻烦事,并且在取出值时会导致虚假的模式匹配。a -> IO rEither

使用Void我们可以首先将a -> IO r转换为 a a -> IO (Either Void r),将其传递给takesACallback,然后使用该absurd :: Void -> a函数删除 Either 上的“假”错误分支。

takesACallback':: (a -> IO r) -> a -> IO r
takesACallback' callback = fmap (either absurd id) 
                         . takesACallback (fmap Right . callback) 

是关于 Hackage 的这个技巧的一个例子。

于 2016-06-24T13:35:16.183 回答