52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 106

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 106

ние. Поскольку мы не можем изменять состояние единственное, что нам остаётся – это принимать значение

состояния на вход вместе с аргументом и возвращать обновлённое состояние на выходе. У нас получится

такой тип:

a -> s -> (b, s)

Функция принимает одно значение типа a и состояние типа s, а возвращает пару, которая состоит из

результата типа b и обновлённого состояния. Если мы введём синоним:

type State s b = s -> (b, s)

И вспомним о частичном применении, то мы сможем записать тип функции с состоянием так:

a -> State s b

В Haskell пошли дальше и выделили для таких функций специальный тип:

data State s a = State (s -> (a, s))

runState :: State s a -> s -> (a, s)

runState (State f) = f

b

c

a

f

b

g

s

s

s

s

b

c

a

g

f

s

s

s

c

a

f*>g

s

s

Рис. 6.7: Композиция функций с состоянием

Функция runState просто извлекает функцию из оболочки State.

На (рис. 6.6) изображена схема функции с состоянием. В сравнении с обычной функцией у такой функции

один дополнительный выход и один дополнительный вход типа s. По ним течёт и изменяется состояние.

Попробуйте по схеме композиции для функций с состоянием написать экземпляры для классов Kleisli

и Monad для типа State s (рис. 6.7).

Подсказка: В этом определении есть одна хитрость, в отличае от типов Maybe и [a] у типа State два

параметра, это параметр состояния и параметр значения. Но мы делаем экземпляр не для State, а для State

s, то есть мы свяжем тип с некоторым произвольным типом s.

instance Kleisli (State s) where

...

Упражнения | 101

a

f