(说是没有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 r
Either
使用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 的这个技巧的一个例子。