52700.fb2
Для того чтобы упорядочить эти вычисления мы воспользуемся типом State. Каждое выражение будет
принимать фиктивное состояние и возвращать его. Тогда функция fun запишется так:
fun :: Int -> State s Int
fun arg = State $ \s0 ->
let (mem, s1)
= runState (new arg)
s0
((),
s2)
= runState (write mem arg)
s1
(x,
s3)
= runState (read mem)
s2
y
= x + 1
((),
s4)
= runState (write mem y)
s3
(z,
s5)
= runState (read mem)
s4
in (z, s5)
new
:: a -> State s (Mem a)
write
:: Mem a -> a -> State s ()
read
:: Mem a -> State s a
Тип Mem параметризован типом значения, которое хранится в памяти. В этом варианте мы не можем
изменить порядок следования выражений, поскольку нам приходится передовать состояние. Мы могли бы
записать это выражение гораздо короче с помощью методов класса Monad, но мне хотелось подчеркнуть как
передача состояния навязывает порядок вычисления. Функция write теперь возвращает пустой кортеж. Но
порядок не теряется за счёт состояния. Пустой кортеж намекает на то, что единственное назначение функции
write – это обновление состояния.
Однако этого не достаточно. Мы хотим, чтобы обновление значения было скрыто от пользователя в чистой
функции. Мы хотим, чтобы тип функции fun не содержал типа State. Для этого нам откуда-то нужно взять
начальное значение состояния. Мы можем решить эту проблему, зафиксировав тип s. Пусть это будет тип
FakeState, скрытый от пользователя.
module Mutable(
Mutable, Mem, purge,
new, read, write)
where
newtype Mutable a = Mutable (State FakeState a)
data FakeState = FakeState
purge :: Mutable a -> a