Da ich die folgenden DSL habe und dessen Dolmetscher (kostenlos Monad verwenden):Haskell: Memoising mit MonadState in einem FreeMonad Interpreter
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
Ich mag den Interpreter intern ändern MonadState zu verwenden, so dass, wenn ein Thing
bereits für einen bestimmten Id
, dann abgerufen worden gibt es keinen zweiten Anruf SomeApi
Lets weiß, dass ich schon davon ausgehen, wie die memoised Version mit get
und put
, aber das Problem, das ich läuft diehabe schreiben 210 innerhalb runMyDsl
. Ich dachte, die Lösung würde wie folgt aussehen:
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 ..
Aber die Typen nicht fluchten, da run
kehrt (.. , MonadState ThingMap m) => m a
und evalStateT
StateT ThingMap m a
erwartet.