StateT
トランスフォーマーを Haste で正しくコンパイルできなかったため、独自の実装を作成しました。setInterval
私の状態モナド内でjavascriptを動かしたかったと思います。への ffi 呼び出しは次のとおりsetInterval
です。
jsInterval :: Int -> IO () -> IO Int
jsInterval = ffi "(function(t,f){window.setInterval(f,t);})"
m
に渡された後に backの結果を取得する方法は考えられませんでしたjsInterval
。ということで使ってみましたIORefs
。
interval :: Int -> StateT s IO () -> StateT s IO Int
interval i m = StateT $ \s -> do
ref <- newIORef Nothing
id_ <- jsInterval i $ do
(_, s') <- runStateT m s
writeIORef ref (Just s')
s' <- readIORef ref
return (id_, s')
元の状態を維持しているため、これは機能しませんでした。書き込みの前に読み取りが行われました。IORef
そのため、が書き込まれるまでループでポーリングする関数を作成しましたが、これは永遠にハングアップしました。
interval :: Int -> StateT s IO () -> StateT s IO Int
interval i m = StateT $ \s -> do
ref <- newIORef Nothing
id_ <- jsInterval i $ do
(_, s') <- runStateT m s
writeIORef ref (Just s')
s' <- go ref
return (id_, s')
where
go ref = do
s <- readIORef ref
case s of
Nothing -> go ref
Just s' -> return s'
この機能を実装することは可能ですか?MonadEvent
forのインスタンスを書き込もうとしましStateT
たが、それも失敗しました。