Для моей библиотеки векторной графики в Haskell я должен переносить довольно большое состояние: параметры линии, цвета, траектории отсечения и т. Д. Я знаю два способа сделать это. Цитата из комментария Haskell-cafe : «Я бы посоветовал вам использовать монаду читателя с изменяемым состоянием или монаду состояния с неизменяемым состоянием».
Вот моя проблема: обновление большого неизменяемого состояния убивает производительность. Использование большого количества STRef схоже с написанием C в Haskell: это многословно и некрасиво.
Вот неизменное состояние:
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 и позволяет собрать старый мусор. Это снижает производительность, когда состояние большое и часто обновляется.
Вот изменяемое состояние:
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 для чтения и обновления большого состояния, но поскольку я сталкиваюсь с Используйте этот шаблон довольно часто, я надеюсь, что есть способ получше.