rad*_*row 4 monads performance haskell state-monad reader-monad
在设计编程模型时,我总是会遇到哪种方法更好的难题:
type MyMonad1 = StateT MyState (Reader Env)
type MyMonad2 = ReaderT Env (State MyState)
Run Code Online (Sandbox Code Playgroud)
在使用一个单子与另一个单子之间有什么好处和取舍?有关系吗?性能如何?
在一般情况下,monad转换器的不同顺序将导致不同的行为,但是正如注释中所指出的,对于“状态”和“阅读器”这两个顺序,我们具有以下同构直到新类型:
StateT MyState (Reader Env) a ~ MyState -> Env -> (a, MyState)
ReaderT Env (State MyState) a ~ Env -> MyState -> (a, MyState)
Run Code Online (Sandbox Code Playgroud)
因此,唯一的区别是参数顺序之一,否则这两个单子在语义上是等效的。
关于性能,如果不对实际代码进行基准测试,就很难确定。但是,作为一个数据点,如果考虑以下单子动作:
foo :: StateT Double (Reader Int) Int
foo = do
n <- ask
modify (* fromIntegral n)
gets floor
Run Code Online (Sandbox Code Playgroud)
然后当使用GHC 8.6.4编译-O2时,newtypes是-很明显-优化掉了,这产生准确,如果你更改签名相同的核心:
foo :: ReaderT Int (State Double) Int
Run Code Online (Sandbox Code Playgroud)
除了foo要翻转的两个参数。因此,至少在这个简单的示例中,根本没有性能差异。
从风格上讲,您可能会遇到一种情况,导致一种顺序比另一种顺序的外观更好看,但是在它们之间通常没有太多选择。特别是,上述任一基本基本动作在任何一种排序下都看起来完全相同。
无缘无故,我倾向于#2,主要是因为Env -> MyState -> (a, MyState)看起来对我来说更自然。
| 归档时间: |
|
| 查看次数: |
90 次 |
| 最近记录: |