【发布时间】:2016-07-15 09:28:06
【问题描述】:
鉴于我有以下 DSL(使用 Free Monad)及其解释器:
data MyDslF next =
GetThingById Int (Thing -> next)
| Log Text next
type MyDslT = FT MyDslF
runMyDsl :: (MonadLogger m, MonadIO m, MonadCatch m) => MyDslT m a -> m a
runMyDsl = iterT run
where
run :: (MonadLogger m, MonadIO m, MonadCatch m) => MyDslF (m a) -> m a
run (Log message continue) = Logger.log message >> continue
run (GetThingById id' continue) = SomeApi.getThingById id' >>= continue
我想在内部更改解释器以使用 MonadState,这样如果已经为给定的 Id 检索到 Thing,则不会再调用 SomeApi
假设我已经知道如何使用get 和put 编写记忆版本,但我遇到的问题是在runMyDsl 中运行MonadState。
我在想解决方案看起来类似于:
type ThingMap = Map Int Thing
runMyDsl :: (MonadLogger m, MonadIO m, MonadCatch m) => MyDslT m a -> m a
runMyDsl = flip evalStateT mempty . iterT run
where
run :: (MonadLogger m, MonadIO m, MonadCatch m, MonadState ThingMap m) => MyDslF (m a) -> m a
run ..
但类型不对齐,因为 run 返回 (.. , MonadState ThingMap m) => m a 而 evalStateT 期望 StateT ThingMap m a。
【问题讨论】:
标签: haskell memoization monad-transformers state-monad free-monad