Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π˜Π·ΡƒΡ‡Π°ΠΉ Haskell Π²ΠΎ имя Π΄ΠΎΠ±Ρ€Π°!Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 85

Автор ΠœΠΈΡ€Π°Π½ Π›ΠΈΠΏΠΎΠ²Π°Ρ‡Π°

newtype State s a = State { runState :: s –> (a, s) }

Π’ΠΈΠΏ State s a – это Ρ‚ΠΈΠΏ вычислСния с состояниСм, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€ΡƒΠ΅Ρ‚ состояниСм Ρ‚ΠΈΠΏΠ° s ΠΈ ΠΈΠΌΠ΅Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚ΠΈΠΏΠ° a.

Как ΠΈ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Control.Monad.Writer, ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Control.Monad.State Π½Π΅ экспортируСт свой конструктор значСния. Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ Π²Π·ΡΡ‚ΡŒ вычислСниС с состояниСм ΠΈ ΠΎΠ±Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π΅Π³ΠΎ Π² newtype State, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ state, которая Π΄Π΅Π»Π°Π΅Ρ‚ Ρ‚ΠΎ ΠΆΠ΅ самоС, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Π» Π±Ρ‹ конструктор State.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Π»ΠΈ, Π² Ρ‡Ρ‘ΠΌ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΡΡƒΡ‚ΡŒ вычислСний с состояниСм ΠΈ ΠΊΠ°ΠΊ ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ Π΄Π°ΠΆΠ΅ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Π² Π²ΠΈΠ΄Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ с контСкстами, Π΄Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим ΠΈΡ… экзСмпляр класса Monad:

instance Monad (State s) where

   return x = State $ \s –> (x, s)

   (State h) >>= f = State $ \s –> let (a, newState) = h s

                                       (State g) = f a

                                   in g newState

Наша Ρ†Π΅Π»ΡŒ использования Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ return состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Π·ΡΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ вычислСниС с состояниСм, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ всСгда содСрТит это Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² качСствС своСго Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΌΡ‹ просто создаём Π°Π½ΠΎΠ½ΠΈΠΌΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ \s –> (x, s). ΠœΡ‹ всСгда прСдставляСм Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ x Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° вычислСния с состояниСм, Π° состояниС остаётся Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Ρ‹ΠΌ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ функция return Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ контСкст. ΠŸΠΎΡ‚ΠΎΠΌΡƒ функция return создаст вычислСниС с состояниСм, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ прСдставляСт ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, Π° состояниС сохраняСт Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Ρ‹ΠΌ.

А Ρ‡Ρ‚ΠΎ насчёт ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ >>=? Ну Ρ‡Ρ‚ΠΎ ΠΆ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ вычислСния с состояниСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ >>= Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ вычислСниС с состояниСм, Π²Π΅Ρ€Π½ΠΎ? ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΌΡ‹ Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌ с ΠΎΠ±Ρ‘Ρ€Ρ‚ΠΊΠΈ newtype State, Π° Π·Π°Ρ‚Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Π°Π½ΠΎΠ½ΠΈΠΌΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ. Π­Ρ‚Π° анонимная функция Π±ΡƒΠ΄Π΅Ρ‚ нашим Π½ΠΎΠ²Ρ‹ΠΌ вычислСниСм с состояниСм. Но Ρ‡Ρ‚ΠΎ ΠΆΠ΅ Π² Π½Π΅ΠΉ происходит? Нам ΠΊΠ°ΠΊΠΈΠΌ-Ρ‚ΠΎ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΈΠ· ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ вычислСния с состояниСм. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ прямо сСйчас ΠΌΡ‹ находимся Π² вычислСнии с состояниСм, Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π²Ρ‹Ρ‡ΠΈΡΠ»Π΅Π½ΠΈΡŽ с состояниСм h нашС Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС s, Ρ‡Ρ‚ΠΎ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π΄Π°Ρ‘Ρ‚ ΠΏΠ°Ρ€Ρƒ ΠΈΠ· Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΈ Π½ΠΎΠ²ΠΎΠ³ΠΎ состояния: (a, newState).



Π”ΠΎ сих ΠΏΠΎΡ€ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Π»ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ >>=, сразу ΠΆΠ΅ послС извлСчСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΈΠ· монадичСского значСния ΠΌΡ‹ примСняли ΠΊ Π½Π΅ΠΌΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ f, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π½ΠΎΠ²ΠΎΠ΅ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Π’ случаС с ΠΌΠΎΠ½Π°Π΄ΠΎΠΉ Writer послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ это сдСлано ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ Π½ΠΎΠ²ΠΎΠ΅ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π½Π°ΠΌ ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ·Π°Π±ΠΎΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎ контСкстС, объСдинив ΠΏΡ€Π΅ΠΆΠ½Π΅Π΅ ΠΈ Π½ΠΎΠ²ΠΎΠ΅ ΠΌΠΎΠ½ΠΎΠΈΠ΄Π½Ρ‹Π΅ значСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ mappend. Π—Π΄Π΅ΡΡŒ ΠΌΡ‹ выполняСм Π²Ρ‹Π·ΠΎΠ² выраТСния f a ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π½ΠΎΠ²ΠΎΠ΅ вычислСниС с состояниСм g. Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Ρƒ нас Π΅ΡΡ‚ΡŒ Π½ΠΎΠ²ΠΎΠ΅ вычислСниС с состояниСм ΠΈ Π½ΠΎΠ²ΠΎΠ΅ состояниС (извСстноС ΠΏΠΎΠ΄ ΠΈΠΌΠ΅Π½Π΅ΠΌ newState), ΠΌΡ‹ просто примСняСм это вычислСниС с состояниСм g ΠΊ newState. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ являСтся ΠΊΠΎΡ€Ρ‚Π΅ΠΆ ΠΈΠ· ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΈ ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ состояния!

Π˜Ρ‚Π°ΠΊ, ΠΏΡ€ΠΈ использовании ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ >>= ΠΌΡ‹ ΠΊΠ°ΠΊ Π±Ρ‹ «склСиваСм» Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ Π΄Π²Π° вычислСния, ΠΎΠ±Π»Π°Π΄Π°ΡŽΡ‰ΠΈΡ… состояниСм. Π’Ρ‚ΠΎΡ€ΠΎΠ΅ вычислСниС скрыто Π²Π½ΡƒΡ‚Ρ€ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ вычислСния. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pop ΠΈ push ΡƒΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ вычислСниями с состояниСм, Π»Π΅Π³ΠΊΠΎ ΠΎΠ±Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΈΡ… Π² ΠΎΠ±Ρ‘Ρ€Ρ‚ΠΊΡƒ State:

import Control.Monad.State


pop :: State Stack Int

pop = state $ \(x:xs) –> (x, xs)


push :: Int –> State Stack ()

push a = state $ \xs –> ((), a:xs)

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΠΊΠ°ΠΊ ΠΌΡ‹ задСйствовали Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ state, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π² конструктор newtype State, Π½Π΅ прибСгая ΠΊ использованию конструктора значСния State Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ.

Ѐункция pop – ΡƒΠΆΠ΅ вычислСниС с состояниСм, Π° функция push ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° Int ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ вычислСниС с состояниСм. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ наш ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ проталкивания числа 3 Π² стСк ΠΈ выталкивания Π΄Π²ΡƒΡ… чисСл ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹ΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

import Control.Monad.State


stackManip :: State Stack Int

stackManip = do

   push 3

   a <– pop

   pop

Π’ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ ΠΌΡ‹ «склСили» ΠΏΡ€ΠΎΡ‚Π°Π»ΠΊΠΈΠ²Π°Π½ΠΈΠ΅ ΠΈ Π΄Π²Π° выталкивания Π² ΠΎΠ΄Π½ΠΎ вычислСниС с состояниСм? Разворачивая Π΅Π³ΠΎ ΠΈΠ· ΠΎΠ±Ρ‘Ρ€Ρ‚ΠΊΠΈ newtype, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π½Π΅ΠΊΠΎΠ΅ исходноС состояниС:

ghci> runState stackManip [5,8,2,1]

(5,[8,2,1])

Нам Π½Π΅ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ ΠΏΡ€ΠΈΠ²ΡΠ·Ρ‹Π²Π°Ρ‚ΡŒ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pop ΠΊ ΠΎΠ±Ρ€Π°Π·Ρ†Ρƒ a, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΌΡ‹ вовсС Π½Π΅ использовали этот ΠΎΠ±Ρ€Π°Π·Π΅Ρ†. Π—Π½Π°Ρ‡ΠΈΡ‚, это ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π²ΠΎΡ‚ Ρ‚Π°ΠΊ:

stackManip :: State Stack Int

stackManip = do

   push 3

   pop

   pop

ΠžΡ‡Π΅Π½ΡŒ ΠΊΡ€ΡƒΡ‚ΠΎ! Но Ρ‡Ρ‚ΠΎ Ссли ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ послоТнСС? Π‘ΠΊΠ°ΠΆΠ΅ΠΌ, Π²Ρ‹Ρ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒ ΠΈΠ· стСка ΠΎΠ΄Π½ΠΎ число, ΠΈ Ссли это число Ρ€Π°Π²Π½ΠΎ 5, просто ΠΏΡ€ΠΎΡ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒ Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Π² стСк ΠΈ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒΡΡ. Но Ссли число Π½Π΅ Ρ€Π°Π²Π½ΠΎ 5, вмСсто этого ΠΏΡ€ΠΎΡ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ 3 ΠΈ 8. Π’ΠΎΡ‚ ΠΎΠ½ ΠΊΠΎΠ΄:

stackStuff :: State Stack ()

stackStuff = do

   a <– pop

   if a == 5

      then push 5

      else do

         push 3

         push 8

Π”ΠΎΠ²ΠΎΠ»ΡŒΠ½ΠΎ простоС Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅. Π”Π°Π²Π°ΠΉΡ‚Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΠΌ этот ΠΊΠΎΠ΄ с исходным стСком:

ghci> runState stackStuff [9,0,2,1,0] ((),[8,3,0,2,1,0])

ВспомнитС, Ρ‡Ρ‚ΠΎ выраТСния do Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ монадичСскиС значСния, ΠΈ ΠΏΡ€ΠΈ использовании ΠΌΠΎΠ½Π°Π΄Ρ‹ State ΠΎΠ΄Π½ΠΎ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ do являСтся Ρ‚Π°ΠΊΠΆΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ с состояниСм. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ stackManip ΠΈ stackStuff ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌΠΈ вычислСниями с состояниСм, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Β«ΡΠΊΠ»Π΅ΠΈΠ²Π°Ρ‚ΡŒΒ» ΠΈΡ… вмСстС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ΡŒ дальнСйшиС вычислСния с состояниСм:

moreStack :: State Stack ()

moreStack = do

   a <– stackManip

   if a == 100

      then stackStuff

      else return ()

Если Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ stackManip ΠΏΡ€ΠΈ использовании Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ стСка Ρ€Π°Π²Π΅Π½ 100, ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ stackStuff; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ. Π’Ρ‹Π·ΠΎΠ² return () просто сохраняСт состояниС ΠΊΠ°ΠΊ Π΅ΡΡ‚ΡŒ ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚.

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈ установка состояния

ΠœΠΎΠ΄ΡƒΠ»ΡŒ Control.Monad.State опрСдСляСт класс Ρ‚ΠΈΠΏΠΎΠ² ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ MonadState, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΡ€ΠΈΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π΄Π²Π΅ вСсьма ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: get ΠΈ put. Для ΠΌΠΎΠ½Π°Π΄Ρ‹ State функция get Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π²ΠΎΡ‚ Ρ‚Π°ΠΊ:

get = state $ \s –> (s, s)

Она просто Π±Π΅Ρ€Ρ‘Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС ΠΈ прСдставляСт Π΅Π³ΠΎ Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.

Ѐункция put ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ состояниС ΠΈ создаёт Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ с состояниСм, которая замСняСт ΠΈΠΌ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС:

put newState = state $ \s –> ((), newState)

ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΈΡ…, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ, Ρ‡Π΅ΠΌΡƒ Ρ€Π°Π²Π΅Π½ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ стСк, Π»ΠΈΠ±ΠΎ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Π΄Ρ€ΡƒΠ³ΠΈΠΌ стСком – Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‚Π°ΠΊ:

stackyStack :: State Stack ()

stackyStack = do

   stackNow <– get

   if stackNow == [1,2,3]

      then put [8,3,1]

      else put [9,2,1]

Π’Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ get ΠΈ put, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pop ΠΈ push. Π’ΠΎΡ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pop:

pop :: State Stack Int

pop = do

   (x:xs) <– get

   put xs

   return x

ΠœΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ get, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ вСсь стСк, Π° Π·Π°Ρ‚Π΅ΠΌ – Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ put, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½ΠΎΠ²Ρ‹ΠΌ состояниСм Π±Ρ‹Π»ΠΈ всС элСмСнты Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ. ПослС Ρ‡Π΅Π³ΠΎ ΠΏΡ€ΠΈΠ±Π΅Π³Π°Π΅ΠΌ ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ return, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ x Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.

Π’ΠΎΡ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ push, Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΠΎΠΉ с использованиСм get ΠΈ put:

push :: Int –> State Stack ()

push x = do

   xs <– get

   put (x:xs)

ΠœΡ‹ просто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ get, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС, ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ put, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ состояниС Π² Ρ‚Π°ΠΊΠΎΠ΅ ΠΆΠ΅, ΠΊΠ°ΠΊ наш стСк с элСмСнтом x Π½Π° Π²Π΅Ρ€ΡˆΠΈΠ½Π΅.

Π‘Ρ‚ΠΎΠΈΡ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, ΠΊΠ°ΠΊΠΈΠΌ Π±Ρ‹Π» Π±Ρ‹ Ρ‚ΠΈΠΏ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ >>=, Ссли Π±Ρ‹ ΠΎΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π»Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ со значСниями ΠΌΠΎΠ½Π°Π΄Ρ‹ State:

(>>=) :: State s a –> (a –> State s b) –> State s b

Π’ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ состояния s остаётся Ρ‚Π΅ΠΌ ΠΆΠ΅, Π½ΠΎ Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ с a Π½Π° b? Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Β«ΡΠΊΠ»Π΅ΠΈΠ²Π°Ρ‚ΡŒΒ» вмСстС нСсколько вычислСний с состояниСм, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΈΠΌΠ΅ΡŽΡ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹, Π½ΠΎ Ρ‚ΠΈΠΏ состояния Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ Ρ‚Π΅ΠΌ ΠΆΠ΅. ΠŸΠΎΡ‡Π΅ΠΌΡƒ ΠΆΠ΅ Ρ‚Π°ΠΊ?.. Ну, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, для Ρ‚ΠΈΠΏΠ° Maybe опСрация >>= ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚Π°ΠΊΠΎΠΉ Ρ‚ΠΈΠΏ:

(>>=) :: Maybe a –> (a –> Maybe b) –> Maybe b

Π›ΠΎΠ³ΠΈΡ‡Π½ΠΎ, Ρ‡Ρ‚ΠΎ сама ΠΌΠΎΠ½Π°Π΄Π° Maybe Π½Π΅ измСняСтся. НС ΠΈΠΌΠ΅Π»ΠΎ Π±Ρ‹ смысла ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ >>= ΠΌΠ΅ΠΆΠ΄Ρƒ двумя Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ ΠΌΠΎΠ½Π°Π΄Π°ΠΌΠΈ. Для ΠΌΠΎΠ½Π°Π΄Ρ‹ State ΠΌΠΎΠ½Π°Π΄ΠΎΠΉ Π½Π° самом Π΄Π΅Π»Π΅ являСтся State s, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ Ссли Π±Ρ‹ этот Ρ‚ΠΈΠΏ s Π±Ρ‹Π» Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌ, ΠΌΡ‹ использовали Π±Ρ‹ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ >>= ΠΌΠ΅ΠΆΠ΄Ρƒ двумя Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ ΠΌΠΎΠ½Π°Π΄Π°ΠΌΠΈ.