5

現在、次のような非同期関数があります。

  foo = do 
     ayncGetNumber "/numberLocation" \a -> 
        (trace <<< show) a

しかし、このコールバック スタイルは構成可能ではありません (私の理解では)。

  foo = do 
     a <- ayncGetNumber "/numberLocation"
     (trace <<< show) a

また

  foo = ayncGetNumber "/numberLocation" >>= show >>> trace

しかし、コールバックから脱出して構成可能にする方法がわかりません。

4

1 に答える 1

8

パッケージの継続モナド変換子の使用を検討することをお勧めしContTます。purescript-transformers

ContTそのパッケージ内の の定義は次のように与えられます

newtype ContT r m a = ContT ((a -> m r) -> m r)

beと be に設定するrと、コンストラクター内のの型に少し似たものが得られます。UnitmEff effasyncGetNumber

(a -> Eff eff Unit) -> Eff eff Unit

これで、必要な効果が含まれていることを確認して、で使用する関数effをラップできるはずです 。asyncGetNumberContT

asyncGetNumberCont :: ContT Unit (Eff SomeEffects) Number
asyncGetNumberCont = ContT $ \callback -> 
  asyncGetNumber "/numberLocation" callback

あるいは単に

asyncGetNumberCont = ContT $ asyncGetNumber "/numberLocation"

への引数は、引数としてコールバックを取ることに注意してくださいContT

do 記法を使用して、非同期計算を直列に構成できるようになりました。

do n <- asyncGetNumberCont
   m <- asyncGetNumberCont
   return (n + m)

ContT非同期計算の並列構成をラップしてサポートするアプリケーション ファンクターを作成することもできます。purescript-node-thunkこの種の機能をそのまま提供するパッケージにも興味があるかもしれません。

編集: 別のオプションはContT、 とは異なる、外部の型を使用して独自の のような型を作成することEffです。これは次のように行うことができます。

-- Ignore effects to keep things simple
-- The runtime representation of 'Async a' is a function which takes a callback,
-- performs some side effects an returns.
foreign import data Async :: * -> *

-- Make an async computation from a function taking a callback
foreign import makeAsync 
  "function makeAsync(f) {\
  \  return function(k) {\
  \    f(function(a) {\
  \      return function() {\
  \        k(a)();\
  \      };\
  \    })();\
  \  };\
  \}" :: forall a eff. ((a -> Eff eff Unit) -> Eff eff Unit) -> Async a

-- Now we need to define instances for Async, which we can do using FFI
-- calls, for example:
foreign import fmapAsync
  "function fmapAsync(f) {\
  \  return function (comp) {\
  \    return function (k) {\
  \      comp(function(a) {\
  \        k(f(a));\
  \      });
  \    };\
  \  };\
  \}" :: forall a b. (a -> b) -> Async a -> Async b

instance functorAsync :: Functor Async where
  (<$>) = fmapAsync

等々。基本的に の実装を繰り返しているため、これはすぐに面倒になりますContT

さらに、コンパイラで書き換えルールがサポートされていないと、 で取得するようなインライン バインドを取得する方法がありませんEff

于 2014-08-21T17:54:39.380 に答える