ST Monad == запах кода?

Я работаю над реализацией алгоритма UCT в Haskell, который требует изрядного количества подтасовка данных. Не вдаваясь в подробности, это алгоритм моделирования, в котором на каждом «шаге» листовой узел в дереве поиска выбирается на основе некоторых статистических свойств, на этом листе создается новый дочерний узел, а статистика соответствует новый лист и все его предки обновляются.

Учитывая все это жонглирование, я недостаточно сообразителен, чтобы понять, как сделать все дерево поиска красивой неизменяемой структурой данных а-ля Окасаки . Вместо этого я немного поигрался с монадой ST , создав структуры, состоящие из изменяемых STRef s. Надуманный пример (не связанный с UCT):

import Control.Monad
import Control.Monad.ST
import Data.STRef

data STRefPair s a b = STRefPair { left :: STRef s a, right :: STRef s b }

mkStRefPair :: a -> b -> ST s (STRefPair s a b)
mkStRefPair a b = do
    a' <- newSTRef a
    b' <- newSTRef b
    return $ STRefPair a' b'

derp :: (Num a, Num b) => STRefPair s a b -> ST s ()
derp p = do
    modifySTRef (left p) (\x -> x + 1)
    modifySTRef (right p) (\x -> x - 1)

herp :: (Num a, Num b) => (a, b)
herp = runST $ do
    p <- mkStRefPair 0 0
    replicateM_ 10 $ derp p
    a <- readSTRef $ left p
    b <- readSTRef $ right p
    return (a, b)

main = print herp -- should print (10, -10)

Очевидно, что этот конкретный пример было бы намного проще написать без использования ST , но, надеюсь, ясно, куда я иду с этим ...Если бы я применил такой стиль к моему варианту использования UCT, это неправильно?

Кто-то задал аналогичный вопрос здесь пару лет назад, но я думаю, что мой вопрос немного другой ... У меня нет проблем с использованием монад для инкапсуляции изменяемого состояния, когда это необходимо, но меня привлекает именно это предложение «когда необходимо». Меня беспокоит, что я преждевременно возвращаюсь к объектно-ориентированному мышлению, когда у меня есть куча объектов с геттерами и сеттерами. Не совсем идиоматический Haskell ...

С другой стороны, если это разумный стиль кодирования для некоторого набора проблем, я думаю, у меня будет вопрос: есть ли какие-нибудь хорошо известные способы сохранить это код читабельный и ремонтопригодный? Меня как бы выбивают из колеи все явные операции чтения и записи, и особенно неприятно то, что мне приходится переводить из моих STRef структур внутри монады ST в изоморфные, но неизменяемые структуры вне.

45
задан Community 23 May 2017 в 12:00
поделиться

2 ответа

Это может быть действительно трудно сказать, когда использование ST целесообразно. Я бы посоветовал вам сделать это с ST и без ST (не обязательно в таком порядке). Держите не-ST версию простой; использование ST следует рассматривать как оптимизацию, и вы не хотите этого делать, пока не поймете, что вам это нужно.

9
ответ дан 26 November 2019 в 21:23
поделиться

Использование монады ST обычно (но не всегда) в качестве оптимизации. Для любой оптимизации я применяю ту же процедуру:

  1. Пишите код без него,
  2. Профилируйте и выявляйте узкие места,
  3. Постепенно переписывайте узкие места и проверяйте улучшения / регрессии,

Другой известный мне вариант использования - это альтернатива государственной монаде. Ключевым отличием является то, что в монаде состояния тип всех хранимых данных указывается сверху вниз, а в монаде ST - снизу вверх. Есть случаи, когда это полезно.

2
ответ дан 26 November 2019 в 21:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: