Haskell - 在Applicative的情况下效果顺序是否确定?

时间:2013-01-10 13:36:43

标签: haskell applicative

执行someFun <$> (a :: IO ()) <$> (b :: IO ())定义的IO操作时,是否执行了ab操作?也就是说,我可以指望在a之前执行b吗?

对于GHC,我可以看到IO是使用State实现的,并且还看到here它是一个Applicative实例,但是找不到实际实例声明的来源。通过State实施表明,不同的IO效应需要是连续的,但没有必要定义它们的顺序。

在GHCi中玩,似乎Appliative保留了效果顺序,但这是一些普遍的保证,还是GHC特定的?我会对细节感兴趣。

import System.Time
import Control.Concurrent
import Data.Traversable
let prec (TOD a b) = b
fmap (map prec) (sequenceA $ replicate 5 (threadDelay 1000 >> getClockTime))

[641934000000,642934000000,643934000000,644934000000,645934000000]

谢谢!

3 个答案:

答案 0 :(得分:18)

肯定是确定性,是的。对于任何特定实例,它总是会做同样的事情。但是,没有固有的理由从右到左选择从左到右的效果顺序。

但是,来自the documentation for Applicative

  

如果f也是Monad,则应该满足pure = return(<*>) = ap(这意味着pure 1}}和<*>满足应用仿函数法则)。

ap的定义来自Control.Monad

ap :: (Monad m) => m (a -> b) -> m a -> m b
ap =  liftM2 id

liftM2以明显的方式定义:

liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }

这意味着,对于Monad以及Applicative的任何算符,预期(按规范,因为这不能在代码中强制执行), Applicative将从左到右工作,因此do中的liftM2阻止与liftA2 f x y = f <$> x <*> y的功能相同。

由于上述原因,即使对于没有相应Applicative的{​​{1}}个实例,按照惯例,效果通常也是从左到右排序。

更广泛地说,因为Monad计算的结构必然与“效果”无关,所以通常可以独立于Applicative效果的排序方式来分析程序的含义。例如,如果Applicative的实例从右到左更改为序列,则使用它的任何代码都会给出相同的结果,只是列表元素的顺序不同。

答案 1 :(得分:4)

是的,订单是由Monad-Applicative通信预先定义的。这很容易看出:(*>)组合子需要与monad中行为良好的(>>)实例中的Applicative组合子对应,其定义为:

a *> b = liftA2 (const id) a b

换句话说,如果在b之前执行了a,则Applicative实例将会出现问题。

编辑:作为旁注:这并未在任何地方明确指定,但您可以找到许多其他类似的对应关系,例如liftM2 = liftA2等。

答案 2 :(得分:2)

对于IO Applicative,情况确实如此。但请查看async package以获取应用的示例,其中['http://www.playhd.video/embed.php?vid=621', 'http://mersalaayitten.com/embed/3752', 'http://www.playhd.video/embed.php?vid=584', 'http://googleplay.tv/videos/kanithan?iframe=true'] f <$> a <*> ba的影响并行发生。