为了我的Haskell矢量图库,我必须携带一个相当大的状态:线条描边参数、颜色、剪辑路径等。我知道两种做法。引用自 Haskell-cafe 的一条评论:“我建议你使用具有可变状态的读取器单子或不可变状态的状态单子。”
这是我的问题:更新一个大的不可变状态会严重影响性能。大量使用STRefs就像在Haskell中编写C语言一样:冗长且丑陋。
这是不可变状态:
data GfxState = GfxState {
lineWidth :: Double,
lineCap :: Int,
color :: Color,
clip :: Path,
...
}
setLineWidth :: Double -> State GfxState ()
setLineWidth x = modify (\state -> state { lineWidth = x })
据我所知,“state { lineWidth = x }” 创建了一个新的 GfxState,然后旧的 GfxState 就会被垃圾回收。当状态很大且经常更新时,这会导致性能下降。
以下是可变状态:data GfxState s = GfxState {
lineWidth :: STRef s Double,
lineCap :: STRef s Int,
color :: STRef s Color,
clip :: STRef s Path,
...
many more STRefs
}
setLineWidth :: GfxState s -> Double -> ST s ()
setLineWidth state x = writeSTRef (lineWidth state) x
现在我到处都可以看到(GfxState s)、(ST s)和(STRef s),这很啰嗦,令人困惑,也违背了编写简短而表达力强代码的精神。我可以使用C + FFI来读取和更新大状态,但由于我经常遇到这种模式,所以我希望有更好的方法。
setLineWidth
?使用更多函数式风格的接口将使实现更具有函数式特性。 - luqui