generated at
Trampolineモナド





使い方

仕組み


Effectとどうやって組み合わせる?
delay ってなに?

実装が異なる
v4
Free Lazy
master
Free ((->) Unit)





元の実装
purs(hs)
-- countDown :: Int -> Int -- countDown 1 = 1 -- countDown n = countDown $ n - 1 -- g = countDown 300000
これでは別にStack Over Flowはしない
コンパイル後のJS見ればわかるが、ちゃんと末尾再帰の最適化されている
ここにlogを仕込むとStack Over Flowするようになる
Effect にしただけでは最適化されているが、logが入ると落ちる
purs(hs)
-- countDown :: Int -> Effect Int -- countDown 1 = pure 1 -- countDown n = do -- log $ show n -- countDown $ n - 1 -- g = countDown 30000
使い方としてはこんな感じ
もともとStack Over Flowしてないので、意味ない
例が悪い
が、使い方の雰囲気としてはこんなかんじだということがわかる
purs(hs)
countDown :: Int -> Trampoline Int countDown 1 = done 1 countDown n = countDown (n - 1) f = runTrampoline $ countDown 100000
じゃあ、trampolineしつつ、log出すのってどうやるの #??
purs(hs)
countDown :: Int -> Trampoline (Effect Unit) -- countDown 1 = done $ liftEffect $ pure 1 countDown 1 = done $ liftEffect $ log "1" countDown n = do -- liftEffect $ delay $ log $ show n _ <- delay $ \_ -> log $ show n countDown (n - 1) f = runTrampoline $ countDown 100000
ちょっと行き詰まっている
コンパイル後のJSにlog仕込めばちゃんと100000回loopしているのがわかる
これでいけた
purs(hs)
module Prac5 where import Prelude import Control.Monad.Free.Trans (FreeT, runFreeT) import Control.Monad.Rec.Class (class MonadRec) import Data.Identity (Identity(..)) import Effect (Effect) import Effect.Class (liftEffect) import Effect.Class.Console (log) runIdentity :: forall a. Identity a -> a runIdentity (Identity a) = a type SafeT = FreeT Identity runSafeT :: forall m a. (MonadRec m) => SafeT m a -> m a runSafeT = runFreeT (pure <<< runIdentity) countDown :: Effect Unit countDown = runSafeT $ go 100000 where go :: Int -> SafeT Effect Unit go 1 = pure unit go n = do liftEffect (log $ show n) go (n-1)
いや、Trampoline使わんのかい、となったmrsekut
いや、Trampolineにwrapできるのかこれ
trunSafeTがrunTrampolineみたいなものか
これ、TrampolineTみたいなものがいるのでは?