В Control.Monad.State
уже есть реализация, но она громоздка из соображений общности: одна сложность связана с классом MonadState, а другая — с тем фактом, что простая State
реализована в терминах более общей StateT
.
Вот пример вашей задачи с использованием этой реализации. Изменчивость не использовалась. Обратите внимание, что ваш пример был вставлен как есть, просто добавлен префикс x
:
import Control.Monad.State
import qualified Data.Map as M
type MyMap a = M.Map Int a
type MyState a b = State (MyMap a) b
type MyRef = Int
xrun :: MyState a b -> b
xrun x = evalState x (M.empty)
mget :: MyState a (MyMap a)
mget = get
mput :: MyMap a -> MyState a ()
mput = put
mmodify :: (MyMap a -> MyMap a) -> MyState a ()
mmodify x = modify x
xnew :: s -> MyState s MyRef
xnew val = do
s <- mget
let newRef = if M.null s then 0 else fst (M.findMax s) + 1
mput $ M.insert newRef val s
return newRef
xset :: MyRef -> a -> MyState a ()
xset ref val = modify $ M.insert ref val
xget :: MyRef -> MyState a a
xget ref = fmap (\s -> case M.lookup ref s of Just v -> v) get
test :: MyState Int Int
test = do
x1 <- xnew 2
xset x1 3
x2 <- xget x1
y1 <- xnew 10
xset y1 20
y2 <- xget y1
return (x2 + y2)
main = print $ xrun test
Возможна реализация всех функций в модуле и >>=
/return
без использования стоковых реализаций из Control.Monad
с сохранением сигнатур.
Вот:
module MyState (State, get, put, modify, evalState) where
newtype State s a = State (s -> (a, s))
evalState :: State s a -> s -> a
evalState (State f) = fst . f
instance Monad (State s) where
return a = State $ \s -> (a, s)
State f >>= g = State $ \s ->
case f s of
(a', s') -> case g a' of
State h -> h s'
instance Functor (State s) where
fmap f (State g) = State $
\s -> case g s of (a, s) -> (f a, s)
get :: State s s
get = State (\s -> (s, s))
put :: s -> State s ()
put s = State $ \_ -> ((), s)
modify :: (s -> s) -> State s ()
modify f = get >>= put . f
Сохраните его в MyState.hs
и замените import Control.Monad.State
на import MyState
.
person
nponeccop
schedule
07.10.2013
put
все состояние, а не конкретную переменную - person Clinton   schedule 07.10.2013x1
иy1
кажутся переменными, аx2
иy2
кажутся значениями; у них должны быть разные типы, поэтому я нахожу название удивительным. Вы знаете об этом? - person Joachim Breitner   schedule 07.10.2013Integer
— это нечто совершенно отличное от именованной ссылки в некотором состоянии; Я действительно предлагаю не давать запутанных имен. - person Joachim Breitner   schedule 07.10.2013