Ответ 1
Я думаю, что вы используете векторный пакет , как в
import Data.Vector.Mutable
Следуя за классом типа PrimMonad
, он приводит к деталям низкого уровня; вещь, которую нужно заметить, это два экземпляра:
instance PrimMonad IO where ...
instance PrimMonad (ST s) where ...
Итак, (PrimMonad m)
- это просто способ сказать m
либо IO
, либо (ST s)
. Это две основные монады, в которых Haskell настроен так, чтобы вы могли мутировать память. Чтобы быть ясным, m
является конструктором типа и применение m
к типу типа Int
дает тип: m Int
.
Чтобы подчеркнуть: IO
и (ST s)
являются особенными, поскольку они позволяют вам "сохранять состояние", используя эту способность для изменения фактической памяти. Они раскрывают эту возможность в необработанной форме, которую скрывает остальная часть Haskell.
Теперь PrimState - это новая вещь: связанный тип данных. В классе типа PrimMonad
есть объявление:
-- | Class of primitive state-transformer monads
class Monad m => PrimMonad m where
-- | State token type
type PrimState m
Тип, который (PrimState m)
будет в вашем коде, зависит от того, что ему присвоил экземпляр для (PrimMonad m)
.
instance PrimMonad IO where
type PrimState IO = RealWorld
instance PrimMonad (ST s) where
type PrimState (ST s) = s
Тип RealWorld
- это внутренняя деталь реализации низкого уровня ввода-вывода в GHC. Тип s
, привязанный к (ST s)
, - это трюк экзистенциального типа, который позволяет runST
доказать, что ничто не изменяемое не удалось избежать монады (ST s)
.
Чтобы сделать тот же самый код в IO
и (ST s)
, тип PrimMonad
type-class (с ассоциированным PrimState
) используется для обеспечения перегрузки ad-hoc.