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

ron*_*ron 15 haskell applicative

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

对于GHC,我可以看到IO是使用State实现的,并且在这里也看到它是一个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]
Run Code Online (Sandbox Code Playgroud)

谢谢!

C. *_*ann 18

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

但是,从以下文档Applicative:

如果f也是a Monad,它应该满足pure= return(<*>)= ap(这意味着pure并且<*>满足应用函子定律).

定义ap是这样的,来自Control.Monad:

ap :: (Monad m) => m (a -> b) -> m a -> m b
ap =  liftM2 id
Run Code Online (Sandbox Code Playgroud)

liftM2以明显的方式定义:

liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
Run Code Online (Sandbox Code Playgroud)

这意味着,对于任何算符这是一个Monad还有一个Applicative,它预计(由规范,因为这不能在代码执行),这Applicative将工作左到右,使doliftM2做同样的事情liftA2 f x y = f <$> x <*> y.

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

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

  • @ron:在实践中,你可以简单地假设`Applicative`实例将从左到右排序,除非他们大声宣布,否则就像`Backwards`包装器一样.请注意,`Monad`实例在其他方面也可能是不明确的 - 例如,反向的`State` monad会向后处理状态值,但类型本身与常规`State`相同.再举一个例子,`[]`有两个可能的'Applicative`实例,甚至除了排序顺序.你无法避免依赖于文档所说的内容. (2认同)