1

Eff我有以下用s 和s编写的程序Aff。按预期运行。那就是它打印出给定的Int并进行异步计算。

type JsonResponse = AffjaxResponse Json
access :: forall e m. Aff (ajax :: AJAX | e) (Either Error JsonResponse)
access = attempt $ get "http://localhost:8080/livesys/Robert"

staging :: forall e. Int -> Eff (console :: CONSOLE | e) Int
staging i = do
    liftEff $ log $ ">>" ++ show i
    return i

main :: forall a. Int -> Aff (ajax :: AJAX, console :: CONSOLE| a) Int
main state = do
    s <- liftEff $ staging state
    a <- liftAff access
    return s

但是,如果我更改其中的调用顺序,main则会发生一些神秘的事情:

main :: forall a. Int -> Aff (ajax :: AJAX, console :: CONSOLE| a) Int
main state = do
    a <- liftAff access
    s <- liftEff $ staging state
    return s

该函数staging现在被调用了两次!呜?

有人可以解释一下吗?

谢谢你的帮助

4

1 回答 1

0

这可能是抛出异常而不是由 Aff 实例中的错误函数处理的情况。当与 结合使用时,这会导致成功函数的重复调用attempt

module Main where

import Prelude
import Data.Either (Either(..))
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (log)
import Control.Monad.Eff.Exception (Error, EXCEPTION, throwException, error)
import Control.Monad.Aff (Aff, makeAff, liftEff', launchAff, attempt)

raise = throwException <<< error


myAff :: forall e. Aff e String
myAff = _unsafeInterleaveAff $ makeAff doIt
  where
    doIt _ success = do
      log "operation"
      raise "it's dead jim" 
      success "done"

main = do
  launchAff $ do
    liftEff' $ log "start"
    myAff

foreign import _unsafeInterleaveAff :: forall e1 e2 a. Aff e1 a -> Aff e2 a

此代码导致doIt被调用两次,但当 Aff 调用被反转时不会。

额外的:

虽然这个功能看起来有点奇怪。也许attempt用更多这样的代替?

exports._attempt = function (Left, Right, aff) {
  return function(success, error) {
    var affCompleted = false;
    try {
      return aff(function(v) {
        affCompleted = true
        success(Right(v));
      }, function(e) {
        affCompleted = true
        success(Left(e));
      });
    } catch (err) {
      if (affCompleted) {
        throw err;
      } else {
        success(Left(err));
      }
    }
  };
}
于 2016-06-12T18:34:10.080 回答