Быстрое обновление большого состояния в Haskell

Для моей библиотеки векторной графики в 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 для чтения и обновления большого состояния, но поскольку я сталкиваюсь с Используйте этот шаблон довольно часто, я надеюсь, что есть способ получше.

12
задан Don Stewart 9 May 2011 в 01:46
поделиться