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

関数が2 回staging呼び出されるようになりました。うーん?

誰でもこれを説明できますか?

ご協力いただきありがとうございます

4

1 に答える 1

0

Aff インスタンスのエラー関数によって処理されるのではなく、例外がスローされている可能性があります。これにより、 と組み合わせて使用​​すると、success 関数が重複して呼び出され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

このコードは が 2 回呼び出されることにつながります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 に答える