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