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

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

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

Если экзСмпляры классов Functor ΠΈ Monad для Ρ‚ΠΈΠΏΠ° ΠΏΠΎΠ΄Ρ‡ΠΈΠ½ΡΡŽΡ‚ΡΡ Π·Π°ΠΊΠΎΠ½Π°ΠΌ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€ΠΎΠ² ΠΈ ΠΌΠΎΠ½Π°Π΄, ΠΌΠ΅ΠΆΠ΄Ρƒ этими двумя Π½Π΅Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ Ρ€Π°Π·Π½ΠΈΡ†Ρ‹ (ΠΈ всС ΠΌΠΎΠ½Π°Π΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ Π΄ΠΎ сих ΠΏΠΎΡ€ встрСчали, ΠΏΠΎΠ΄Ρ‡ΠΈΠ½ΡΡŽΡ‚ΡΡ ΠΎΠ±ΠΎΠΈΠΌ). Π­Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ ΠΊΠ°ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pure ΠΈ return, Π΄Π΅Π»Π°ΡŽΡ‰ΠΈΠ΅ ΠΎΠ΄Π½ΠΎ ΠΈ Ρ‚ΠΎ ΠΆΠ΅, – Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄Π½Π° ΠΈΠΌΠ΅Π΅Ρ‚ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ класса Applicative, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ другая ΠΈΠΌΠ΅Π΅Ρ‚ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ Monad.

Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ liftM:

ghci> liftM (*3) (Just 8)

Just 24

ghci> fmap (*3) (Just 8)

Just 24

ghci> runWriter $ liftM not $ Writer (True, "Π³ΠΎΡ€ΠΎΡ…")

(False,"Π³ΠΎΡ€ΠΎΡ…")

ghci> runWriter $ fmap not $ Writer (True, "Π³ΠΎΡ€ΠΎΡ…")

(False,"Π³ΠΎΡ€ΠΎΡ…")

ghci> runState (liftM (+100) pop) [1,2,3,4]

(101,[2,3,4])

ghci> runState (fmap (+100) pop) [1,2,3,4]

(101,[2,3,4])

Π’Ρ‹ ΡƒΠΆΠ΅ довольно Ρ…ΠΎΡ€ΠΎΡˆΠΎ Π·Π½Π°Π΅Ρ‚Π΅, ΠΊΠ°ΠΊ функция fmap Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ со значСниями Ρ‚ΠΈΠΏΠ° Maybe. И функция liftM Π΄Π΅Π»Π°Π΅Ρ‚ Ρ‚ΠΎ ΠΆΠ΅ самоС. ΠŸΡ€ΠΈ использовании со значСниями Ρ‚ΠΈΠΏΠ° Writer функция ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ являСтся Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ. Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ fmap ΠΈΠ»ΠΈ liftM с вычислСниСм, ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠΌ состояниС, Π΄Π°Ρ‘Ρ‚ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π΄Ρ€ΡƒΠ³ΠΎΠ΅ вычислСниС с состояниСм, Π½ΠΎ Π΅Π³ΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ измСняСтся Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ. Если Π±Ρ‹ ΠΌΡ‹ Π½Π΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ pop с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ (+100) ΠΏΠ΅Ρ€Π΅Π΄ Ρ‚Π΅ΠΌ, ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Π΅Ρ‘, ΠΎΠ½Π° Π±Ρ‹ Π²Π΅Ρ€Π½ΡƒΠ»Π° (1, [2,3,4]).

Π’ΠΎΡ‚ ΠΊΠ°ΠΊ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° функция liftM:

liftM :: (Monad m) => (a –> b) –> m a –> m b

liftM f m = m >>= (\x –> return (f x))

Или с использованиСм Π½ΠΎΡ‚Π°Ρ†ΠΈΠΈ do:

liftM :: (Monad m) => (a –> b) –> m a –> m b

liftM f m = do

   x <– m

   return (f x)

ΠœΡ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‘ΠΌ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ m Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Π° Π·Π°Ρ‚Π΅ΠΌ примСняСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΊ Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Π² контСкст ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Π’Π²ΠΈΠ΄Ρƒ монадичСских Π·Π°ΠΊΠΎΠ½ΠΎΠ² гарантируСтся, Ρ‡Ρ‚ΠΎ функция Π½Π΅ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ контСкст; ΠΎΠ½Π° измСняСт лишь Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдставляСт монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

Π’Ρ‹ Π²ΠΈΠ΄ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ функция liftM Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° совсСм Π½Π΅ ΡΡΡ‹Π»Π°ΡΡΡŒ Π½Π° класс Ρ‚ΠΈΠΏΠΎΠ² Functor. Π—Π½Π°Ρ‡ΠΈΡ‚, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ fmap (ΠΈΠ»ΠΈ liftM – Π½Π°Π·Ρ‹Π²Π°ΠΉΡ‚Π΅, ΠΊΠ°ΠΊ ΠΏΠΎΠΆΠ΅Π»Π°Π΅Ρ‚Π΅), ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ лишь Ρ‚Π΅ Π±Π»Π°Π³Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ Π½Π°ΠΌ ΠΌΠΎΠ½Π°Π΄Ρ‹. Благодаря этому ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠ½Π°Π΄Ρ‹, ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅, Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΆΠ΅ ΡΠΈΠ»ΡŒΠ½Ρ‹, насколько ΠΈ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Ρ‹.

Класс Ρ‚ΠΈΠΏΠΎΠ² Applicative позволяСт Π½Π°ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ значСниями с контСкстами, ΠΊΠ°ΠΊ Ссли Π±Ρ‹ ΠΎΠ½ΠΈ Π±Ρ‹Π»ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌΠΈ значСниями, Π²ΠΎΡ‚ Ρ‚Π°ΠΊ:

ghci> (+) <$> Just 3 <*> Just 5

Just 8

ghci> (+) <$> Just 3 <*> Nothing

Nothing

ИспользованиС этого Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ стиля всё ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ <$> – это просто функция fmap, Π° опСрация <*> – это функция ΠΈΠ· класса Ρ‚ΠΈΠΏΠΎΠ² Applicative, которая ΠΈΠΌΠ΅Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ‚ΠΈΠΏ:

(<*>) :: (Applicative f) => f (a –> b) –> f a –> f b

Π’Π°ΠΊ Ρ‡Ρ‚ΠΎ это Π²Ρ€ΠΎΠ΄Π΅ fmap, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ сама функция находится Π² контСкстС. Нам Π½ΡƒΠΆΠ½ΠΎ ΠΊΠ°ΠΊΠΈΠΌ-Ρ‚ΠΎ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ Π΅Ρ‘ ΠΈΠ· контСкста ΠΈ с Π΅Ρ‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ f a, Π° Π·Π°Ρ‚Π΅ΠΌ вновь ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ контСкст. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ всС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² языкС Haskell ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΊΠ°Ρ€Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ сочСтаниС ΠΈΠ· ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ <$> ΠΈ <*> ΠΌΠ΅ΠΆΠ΄Ρƒ Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌΠΈ значСниями, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰ΠΈΠ΅ нСсколько ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ².

Однако, оказываСтся, ΠΊΠ°ΠΊ ΠΈ функция fmap, опСрация <*> Ρ‚ΠΎΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π°, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ лишь Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π΄Π°Ρ‘Ρ‚ Π½Π°ΠΌ класс Ρ‚ΠΈΠΏΠΎΠ² Monad. Ѐункция ap, ΠΏΠΎ сущСству, – это <*>, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ΠΌ Monad, Π° Π½Π΅ Applicative. Π’ΠΎΡ‚ Π΅Ρ‘ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅:

ap :: (Monad m) => m (a –> b) –> m a –> m b

ap mf m = do

   f <– mf

   x <– m

   return (fx)

Ѐункция ap – монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ – функция. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ функция, ΠΊΠ°ΠΊ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, находится Π² контСкстС, ΠΌΡ‹ Π±Π΅Ρ€Ρ‘ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈΠ· контСкста ΠΈ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌ Π΅Ρ‘ f, Π·Π°Ρ‚Π΅ΠΌ Π±Π΅Ρ€Ρ‘ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌ Π΅Π³ΠΎ x, ΠΈ, Π² ΠΊΠΎΠ½Ρ†Π΅ ΠΊΠΎΠ½Ρ†ΠΎΠ², примСняСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΊ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ ΠΈ прСдставляСм это Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. Π’ΠΎΡ‚ быстрая дСмонстрация:

ghci> Just (+3) <*> Just 4

Just 7

ghci> Just (+3) `ap` Just 4

Just 7

ghci> [(+1),(+2),(+3)] <*> [10,11]

[11,12,12,13,13,14]

ghci> [(+1),(+2),(+3)] `ap` [10,11]

[11,12,12,13,13,14]

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π°ΠΌ Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠ½Π°Π΄Ρ‹ Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΆΠ΅ ΡΠΈΠ»ΡŒΠ½Ρ‹, насколько ΠΈ Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Ρ‹, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ класса Monad для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΈΠ· класса Applicative. На самом Π΄Π΅Π»Π΅, ΠΊΠΎΠ³Π΄Π° обнаруТиваСтся, Ρ‡Ρ‚ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ являСтся ΠΌΠΎΠ½Π°Π΄ΠΎΠΉ, Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ сначала Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ экзСмпляр класса Monad, Π° Π·Π°Ρ‚Π΅ΠΌ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ экзСмпляр класса Applicative, просто говоря, Ρ‡Ρ‚ΠΎ функция pure – это return, Π° опСрация <*> – это ap. Аналогичным ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ссли Ρƒ вас ΡƒΠΆΠ΅ Π΅ΡΡ‚ΡŒ экзСмпляр класса Monad для Ρ‡Π΅Π³ΠΎ-Π»ΠΈΠ±ΠΎ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ для Π½Π΅Π³ΠΎ экзСмпляр класса Functor, просто говоря, Ρ‡Ρ‚ΠΎ функция fmap – это liftM.

Ѐункция liftA2 вСсьма ΡƒΠ΄ΠΎΠ±Π½Π° для примСнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ двумя Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌΠΈ значСниями. Она ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° Π²ΠΎΡ‚ Ρ‚Π°ΠΊ:

liftA2 :: (Applicative f) => (a –> b –> c) –> f a –> f b –> f c

liftA2 f x y = f <$> x <*> y

Ѐункция liftM2 Π΄Π΅Π»Π°Π΅Ρ‚ Ρ‚ΠΎ ΠΆΠ΅, Π½ΠΎ с использованиСм ограничСния Monad. Π•ΡΡ‚ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ liftM3, liftM4 ΠΈ liftM5.

Π’Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Π»ΠΈ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠ½Π°Π΄Ρ‹ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ ΡΠΈΠ»ΡŒΠ½Ρ‹, Ρ‡Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Ρ‹ ΠΈ Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Ρ‹ – ΠΈ, хотя всС ΠΌΠΎΠ½Π°Π΄Ρ‹, ΠΏΠΎ сути, ΡΠ²Π»ΡΡŽΡ‚ΡΡ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Π°ΠΌΠΈ ΠΈ Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌΠΈ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Π°ΠΌΠΈ, Ρƒ Π½ΠΈΡ… Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ экзСмпляры классов Functor ΠΈ Applicative. ΠœΡ‹ ΠΈΠ·ΡƒΡ‡ΠΈΠ»ΠΈ монадичСскиС эквивалСнты Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Π°ΠΌΠΈ ΠΈ Π°ΠΏΠΏΠ»ΠΈΠΊΠ°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌΠΈ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Π°ΠΌΠΈ.

Ѐункция join

Π•ΡΡ‚ΡŒ ΠΊΠΎΠ΅-какая ΠΏΠΈΡ‰Π° для Ρ€Π°Π·ΠΌΡ‹ΡˆΠ»Π΅Π½ΠΈΡ: Ссли Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ монадичСского значСния – Π΅Ρ‰Ρ‘ ΠΎΠ΄Π½ΠΎ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (ΠΎΠ΄Π½ΠΎ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π²Π»ΠΎΠΆΠ΅Π½ΠΎ Π² Π΄Ρ€ΡƒΠ³ΠΎΠ΅), ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π»ΠΈ Π²Ρ‹ Β«Ρ€Π°Π·Π³Π»Π°Π΄ΠΈΡ‚ΡŒΒ» ΠΈΡ… Π΄ΠΎ ΠΎΠ΄Π½ΠΎΠ³ΠΎ лишь ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ монадичСского значСния? НапримСр, Ссли Ρƒ нас Π΅ΡΡ‚ΡŒ Just (Just 9), ΠΌΠΎΠΆΠ΅ΠΌ Π»ΠΈ ΠΌΡ‹ ΠΏΡ€Π΅Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ это Π² Just 9? ΠžΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ любоС Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π·Π³Π»Π°ΠΆΠ΅Π½ΠΎ, ΠΏΡ€ΠΈΡ‡Ρ‘ΠΌ Π½Π° самом Π΄Π΅Π»Π΅ это свойство ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎ для ΠΌΠΎΠ½Π°Π΄. Для этого Ρƒ нас Π΅ΡΡ‚ΡŒ функция join. Π•Ρ‘ Ρ‚ΠΈΠΏ Ρ‚Π°ΠΊΠΎΠ²:

join :: (Monad m) => m (m a) –> m a

Π—Π½Π°Ρ‡ΠΈΡ‚, функция join ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² монадичСском Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΈ ΠΈ ΠΎΡ‚Π΄Π°Ρ‘Ρ‚ Π½Π°ΠΌ просто монадичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅; Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, ΠΎΠ½Π° Π΅Π³ΠΎ Ρ€Π°Π·Π³Π»Π°ΠΆΠΈΠ²Π°Π΅Ρ‚. Π’ΠΎΡ‚ ΠΎΠ½Π° с Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ значСниями Ρ‚ΠΈΠΏΠ° Maybe:

ghci> join (Just (Just 9))

Just 9

ghci> join (Just Nothing)

Nothing

ghci> join Nothing

Nothing

Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΉ строкС – ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ΅ вычислСниС ΠΊΠ°ΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ вычислСния, поэтому ΠΎΠ½ΠΈ ΠΎΠ±Π° просто соСдинСны Π² ΠΎΠ΄Π½ΠΎ большоС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ΅ вычислСниС. Π’ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ строкС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Nothing прСдставлСно ΠΊΠ°ΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ значСния Just. Всякий Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ Ρ€Π°Π½ΡŒΡˆΠ΅ ΠΈΠΌΠ΅Π»ΠΈ Π΄Π΅Π»ΠΎ со значСниями Maybe ΠΈ Ρ…ΠΎΡ‚Π΅Π»ΠΈ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ нСсколько этих Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ – Π±ΡƒΠ΄ΡŒ Ρ‚ΠΎ с использованиСм ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ <*> ΠΈΠ»ΠΈ >>= – всС ΠΎΠ½ΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Π»ΠΈ Π±Ρ‹Ρ‚ΡŒ значСниями конструктора Just, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ стало Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Just. Если Π½Π° ΠΏΡƒΡ‚ΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π»Π° Ρ…ΠΎΡ‚ΡŒ ΠΎΠ΄Π½Π° Π½Π΅ΡƒΠ΄Π°Ρ‡Π°, Ρ‚ΠΎ ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ являлась Π½Π΅ΡƒΠ΄Π°Ρ‡Π°; Π½Π΅Ρ‡Ρ‚ΠΎ Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎΠ΅ происходит ΠΈ здСсь. Π’ Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ строкС ΠΌΡ‹ пытаСмся Ρ€Π°Π·Π³Π»Π°Π΄ΠΈΡ‚ΡŒ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ вслСдствиС Π½Π΅ΡƒΠ΄Π°Ρ‡ΠΈ, поэтому Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ – Ρ‚Π°ΠΊΠΆΠ΅ Π½Π΅ΡƒΠ΄Π°Ρ‡Π°.

Π Π°Π·Π³Π»Π°ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ списков осущСствляСтся довольно ΠΈΠ½Ρ‚ΡƒΠΈΡ‚ΠΈΠ²Π½ΠΎ:

ghci> join [[1,2,3],[4,5,6]]

[1,2,3,4,5,6]

Как Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ, функция join для списков – это просто concat. Π§Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·Π³Π»Π°Π΄ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΌΠΎΠ½Π°Π΄Ρ‹ Writer, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ сам являСтся Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΌΠΎΠ½Π°Π΄Ρ‹ Writer, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΌΠΎΠ½ΠΎΠΈΠ΄Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ mappend:

ghci> runWriter $ join (Writer (Writer (1, "aaa"), "bbb"))

(1,"bbbaaa")

Π’Π½Π΅ΡˆΠ½Π΅Π΅ ΠΌΠΎΠ½ΠΎΠΈΠ΄Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ "bbb" ΠΈΠ΄Ρ‘Ρ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ, Π·Π°Ρ‚Π΅ΠΌ ΠΊ Π½Π΅ΠΌΡƒ конкатСнируСтся строка "aaa". На ΠΈΠ½Ρ‚ΡƒΠΈΡ‚ΠΈΠ²Π½ΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ значСния Ρ‚ΠΈΠΏΠ° Writer, сначала Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΅Π³ΠΎ ΠΌΠΎΠ½ΠΎΠΈΠ΄Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² ΠΆΡƒΡ€Π½Π°Π», ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΡ‚ΠΎΠΌ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ находится Π²Π½ΡƒΡ‚Ρ€ΠΈ Π½Π΅Π³ΠΎ.

Π Π°Π·Π³Π»Π°ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΌΠΎΠ½Π°Π΄Ρ‹ Either ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΡ…ΠΎΠΆΠ΅ Π½Π° Ρ€Π°Π·Π³Π»Π°ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΌΠΎΠ½Π°Π΄Ρ‹ Maybe:

ghci> join (Right (Right 9)) :: Either String Int

Right 9

ghci> join (Right (Left "ошибка")) :: Either String Int

Left "ошибка"

ghci> join (Left "ошибка") :: Either String Int

Left "ошибка"

Если ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ join ΠΊ Π²Ρ‹Ρ‡ΠΈΡΠ»Π΅Π½ΠΈΡŽ с состояниСм, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся вычислСниСм с состояниСм, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ Π±ΡƒΠ΄Π΅Ρ‚ вычислСниС с состояниСм, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ сначала выполняСт внСшнСС вычислСниС с состояниСм, Π° Π·Π°Ρ‚Π΅ΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅. ВзглянитС, ΠΊΠ°ΠΊ это Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚:

ghci> runState (join (state $ \s –> (push 10, 1:2:s))) [0,0,0]