Advertisement
Guest User

Untitled

a guest
Sep 17th, 2013
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Control.Monad(replicateM)
  2.  
  3. --Наша монада состояния
  4. --Представляет собой функцияю из одного состояния в другое
  5. --st -> (a, st) : здесь st - состояние, a - тип значения которым оперирует монада
  6. --Функция принимает состояние st и возвращает пару (значение, состояние)
  7. --ТИП st меняться не будет, это только тип-параметр нашего состояния, к монадам отношения не имеет
  8. --ТИП а - будет постоянно меняться, один тип-параметр у монады должен быть по определению.
  9. --State Int a, IO a, [a], Maybe a
  10.  
  11. data State st a = State (st -> (a, st))
  12.  
  13. --Итак - определение State st как монады.
  14. instance Monad (State st) where
  15. --Оператор последовательного соединения (>>) (pipeline)
  16. --ЯВНО ОПРЕДЕЛЯТЬ ЕГО НЕ ОБЯЗАТЕЛЬНО. ОН МОЖЕТ БЫТЬ ВЫВЕДЕН ИЗ ОПЕРАТОРА (>>=) но мы определим в учебных целях =)
  17. --Тип :: Monad m => m a -> m b -> m b -- принимает две монады и возвращает "результат слияния"
  18. --    значение у новой монады берётся из второй
  19. --Возвращает новую монаду State st, функция которой определена как st = f2 (snd (f1 st)))
  20. --Функция принимает состояние st и возвращает результат f2(функции второй монады)
  21. --   от второго элементы пары, возвращаемого результатом f1 от состояния(st).
  22. --короче говоря состояние передаётся функции первой монады, второй элемент
  23. --полученой пары(новое состояние) передаётся функции второй монады, которая в свою очередь возвращает состояние
  24. --более краткая запись функции "\st -> f2 (snd (f1 st)))" выглядит так: "f2 . snd . f1"
  25.     State f1 >> State f2 = State (\st -> f2 (snd (f1 st)))
  26.    
  27. --Оператор соединения с "монадической" функцией (>>=) (bind)
  28. --Тип :: Monad m => m a -> (a -> m b) -> m b
  29. --Допустим у нас есть монада, читающая строку из ввода getLine :: IO String
  30. --И функция, создающая монаду при помощи строки(монадическая) putStr :: String -> IO ()
  31. --тогда можно воспользоваться данным оператором: getLine >>= putStr
  32. --функция новой монады исполняет функцию первой монады (f1), с помощью её результата получает f2
  33. --и дальше действует аналогично приведённой выше.
  34.     State f1 >>= mF = State (\st -> let (x, st2) = f1 st
  35.                                         State f2 = mF x
  36.                                     in f2 st2)
  37. --Функция return (unit)
  38. --Тип :: Monad m => a -> m a
  39. --ничего не делает с состоянием, какое принимает, такое и возвращает.
  40. --Зато возвращает х как первый элемент пары. Т.е устанавливает значение монады
  41.     return x = State (\st -> (x, st))
  42.  
  43.  
  44.  
  45. --Итак, наша монада готова, добавим способы для работы с ней
  46.  
  47. --запустить: принимает состояние, и передаёт его функции монады State, результат возвращает
  48. runState :: st -> State st a -> (a, st)
  49. runState st (State f1) = f1 st
  50.  
  51. --Принимает функцию, возвращает монаду модифицирующую состояние
  52. modify :: (st -> st) -> State st ()
  53. modify f = State (\st -> ((), f st))
  54.  
  55. --Функция для примера работы с монадическим значением. Вычисляет чётное ли состояние(числовое, Int)
  56. --Результат возвращается как значение монады
  57. evenSt :: State Int Bool
  58. evenSt = State (\st -> (even st, st))
  59.    
  60. --собственно, работа с числовой монадой состояния.
  61. main = print $ runState 0 $ do --вывод результата запуска нижепреведённой монады с числовым состоянием 0
  62.     modify (+1) --модифицировать состояние, прибавить 1
  63.     replicateM 100 (modify (+1)) --то же самое, повторённое 100 раз
  64.     evenSt --последняя монада, определяющая монадическое значение.
  65. --результат деятельности: (False,101)
  66.  
  67. --В итоге State создаёт портянку из функций, модифицирующий состояние, которые начнут
  68. --рекурсивно дёргать друг друга при "запуске монады".
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement