Saf*_*ron 6 monads haskell repa
我很困惑为什么 REPA 函数computeP
将其结果打包在一个 monad 中。它具有以下类型签名。
computeP :: (Load r1 sh e, Target r2 e, Source r2 e, Monad m) =>
Array r1 sh e -> m (Array r2 sh e)
Run Code Online (Sandbox Code Playgroud)
在本教程中它说
这样做的原因是monad 给出了一个明确定义的序列概念,因此计算 P 强制在 monadic 计算的特定点完成并行评估。
同样,Stack Overflow 上的这个答案指出
Repa 中的并行计算必须是 monadic 的原因部分与懒惰有关,但主要是因为 Repa 无法处理嵌套并行性。Monad 的顺序属性在很大程度上解决了这个问题[.]
例如computeP
:对使用哪个 monad 没有限制,所以我可以使用身份 monad。那么可以使用下面的函数来代替解包 monad,还是会因为它缺少这个顺序属性而产生意想不到的结果?如果可以的话,甚至有必要使用 monad 吗?
import Data.Functor.Identity
import Data.Array.Repa.Eval
import Data.Array.Repa
myComputeP :: (Load r1 sh e, Target r2 e, Source r2 e) => Array r1 sh e -> Array r2 sh e
myComputeP = runIdentity . computeP
Run Code Online (Sandbox Code Playgroud)任何帮助都会很棒。
这个单子约束是一种启发式技巧。它可以帮助有纪律的用户避免嵌套并行,但对恶意或无知的用户没有任何作用。
嵌套并行是指在并行计算某个数组时,最终必须并行计算另一个数组的情况。Repa不支持它(原因并不重要),所以它尽量避免它。
的类型computeP
有助于确保并行计算彼此按顺序完成,但它远非无懈可击;它只是一个“尽力而为”的抽象。
Monad 如何强制执行此操作?
实际上,computeP
仅适用于其第一个参数绑定(>>=)
严格的 monad,因此在 中u >>= k
,该函数仅在评估k
后才会应用。那么如果你与这样的 monad 一起u
使用,computeP
do w <- computeP v
k w
Run Code Online (Sandbox Code Playgroud)
确保向量w
在传递给 之前被评估k
,这可以安全地执行其他computeP
操作。
IO
、 strict State
、Maybe
、[]
。Identity
、惰性State
、Reader
。(惰性 monad 可以变得严格,但反之则不然。特别是,如果您只想进行 Repa 计算,则可以定义严格的恒等 monad。)为了防止嵌套并行性, 的类型computeP
故意使其在可能并行完成的操作中使用起来很麻烦,例如采用非单子函数的map :: (a -> b) -> Array _ _ a -> Array _ _ b
和。fromFunction :: sh -> (sh -> a) -> Array _ _ a
人们仍然可以明确地打开computeP
,例如,正如runIdentity
您所注意到的:如果您愿意,您可以朝自己的脚开枪,但需要您来装载枪,将其指向下方并扣动扳机。
希望这能回答 Repa 正在发生的事情。以下是回答另一个问题的理论题外话:
拥有这个“顺序属性”到底意味着什么?
这些引文相当手气。在我看来,“顺序性”和“单子”之间的关系是双重的。
首先,对于 Haskell 中的许多 monad, 的定义(>>=)
自然决定了求值的顺序,通常是因为它立即与第一个参数进行模式匹配。正如前面所解释的,这就是 Repa 所依赖的强制computeP
计算按顺序发生的原因(这就是为什么如果你将它专门化为 的话它会中断Identity
;它不是一个严格的 monad)。从总体上看,这是惰性求值的一个相当小的细节,而不是一般而言适合 monad 的任何东西。
其次,纯函数式编程的一个核心思想是一流的计算,具有效果和组合的明确定义。在这种情况下,效果是向量的并行计算,而我们关心的组合是顺序组合。Monad 为顺序组合提供了通用模型或接口。这也是 monad 帮助解决 Repa 中避免嵌套并行问题的部分原因。
重点不是单子具有固有的顺序方面,而是顺序组合本质上是单子:如果您尝试列出您期望从任何名副其实的“顺序组合”名称中获得的一般属性,那么您很可能会结束一起被称为“monad”的属性;这是 Moggi 的开创性论文“计算和单子的概念”的要点之一。
“Monad”并不是一个神奇的概念,而是非常普遍的,所以很多东西碰巧都是单子。毕竟,主要要求是存在关联操作;这是关于顺序组合的一个非常合理的假设。(如果,当您听到“结合性”时,您会想到“幺半群”或“类别”,请注意,所有这些概念都统一在“幺半群对象”的保护伞下,因此就“结合性”而言,它们是都是相同的想法,只是属于不同的类别。)