ond*_*dra 10 performance haskell monad-transformers
我有代码根据指定的规则进行一些文件解析.整个解析发生在monad中,它是ReaderT/STTrans/ErrorT的堆栈.
type RunningRule s a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String Identity)) a
Run Code Online (Sandbox Code Playgroud)
因为在代码中运行一些IO会很方便(例如查询外部数据库),我想我会概括解析,这样它就可以在Identity或IO base monad中运行,具体取决于我想要的功能.这将签名更改为:
type RunningRule s m a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String m)) a
Run Code Online (Sandbox Code Playgroud)
在更改了适当的类型签名(并使用一些扩展来绕过类型)之后,我再次在Identity monad中运行它,它的速度慢了约50%.虽然基本没什么变化,但速度要慢得多.这是正常的行为吗?有一些简单的方法可以让它更快吗?(例如,将ErrorT和ReaderT(以及可能的STT)堆栈组合成一个monad变换器?)
要添加代码示例 - 基于解析的输入(以类C语言给出)构建解析器是一件事.代码如下所示:
compileRule :: forall m. (Monad m, Functor m) =>
-> [Data -> m (Either String Data)] -- For tying the knot
-> ParsedRule -- This is the rule we are compiling
-> Data -> m (Either String Data) -- The real parsing
compileRule compiled (ParsedRule name parsedlines) =
\input -> runRunningRule input $ do
sequence_ compiledlines
where
compiledlines = map compile parsedlines
compile (Expression expr) = compileEx expr >> return ()
compile (Assignment var expr) =
...
compileEx (Function "check" expr) = do
value <- expr
case value of
True -> return ()
False -> fail "Check failed"
where
code = compileEx expr
Run Code Online (Sandbox Code Playgroud)
dfe*_*uer 12
这不是那么不寻常,不.你应该尝试使用SPECIALIZEpragma来专攻Identity,也许IO也可以.使用-ddump-simpl并观察有关规则左侧太复杂的警告.当专业化没有发生时,GHC最终会在运行时传递类词类字典.这本质上是效率低下的,但更重要的是它阻止了GHC内联类方法以实现进一步的简化.