Trampolineモナド
使い方
仕組み
Effectとどうやって組み合わせる?
delayってなに?
実装が異なる
v4
Free Lazy
master
Free ((->) Unit)
例
元の実装
code:purs(hs)
-- countDown :: Int -> Int
-- countDown 1 = 1
-- countDown n = countDown $ n - 1
-- g = countDown 300000
Effectにしただけでは最適化されているが、logが入ると落ちる
code:purs(hs)
-- countDown :: Int -> Effect Int
-- countDown 1 = pure 1
-- countDown n = do
-- log $ show n
-- countDown $ n - 1
-- g = countDown 30000
使い方としてはこんな感じ
例が悪い
が、使い方の雰囲気としてはこんなかんじだということがわかる
code:purs(hs)
countDown :: Int -> Trampoline Int
countDown 1 = done 1
countDown n = countDown (n - 1)
f = runTrampoline $ countDown 100000
じゃあ、trampolineしつつ、log出すのってどうやるの #?? code: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しているのがわかる
これでいけた
code: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.icon
いや、Trampolineにwrapできるのかこれ
trunSafeTがrunTrampolineみたいなものか
これ、TrampolineTみたいなものがいるのでは?