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

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

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

НСт Π»ΡƒΡ‡ΡˆΠ΅Π³ΠΎ способа ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ класс Ρ‚ΠΈΠΏΠΎΠ² Functor, Ρ‡Π΅ΠΌ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ, ΠΊΠ°ΠΊ ΠΎΠ½ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½. Π’ΠΎΡ‚ ΠΈ посмотрим:

fmap :: (a -> b) -> f a -> f b

Π˜Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎ Ρƒ нас имССтся? Класс опрСдСляСт ΠΎΠ΄Π½Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ fmap ΠΈ Π½Π΅ прСдоставляСт для Π½Π΅Ρ‘ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Π’ΠΈΠΏ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fmap вСсьма интСрСсСн. Π’ΠΎ всСх Π²Ρ‹ΡˆΠ΅ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½Ρ‹Ρ… опрСдСлСниях классов Ρ‚ΠΈΠΏΠΎΠ² Ρ‚ΠΈΠΏ-ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, ΠΈΠ³Ρ€Π°Π²ΡˆΠΈΠΉ Ρ€ΠΎΠ»ΡŒ Ρ‚ΠΈΠΏΠ° Π² классС, Π±Ρ‹Π» Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, ΠΊΠ°ΠΊ пСрСмСнная a Π² сигнатурС (==) :: (Eq a) => a –> a –> Bool. Но Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Ρ‚ΠΈΠΏ-ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ f Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° (Π½Π΅Ρ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ пСрСмСнная, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Int, Bool ΠΈΠ»ΠΈ Maybe String); Π² этом случаС пСрСмСнная – конструктор Ρ‚ΠΈΠΏΠΎΠ², ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰ΠΈΠΉ ΠΎΠ΄ΠΈΠ½ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€. (Напомню: Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Maybe Int являСтся ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ‚ΠΈΠΏΠΎΠΌ, Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Maybe – конструктор Ρ‚ΠΈΠΏΠΎΠ² с ΠΎΠ΄Π½ΠΈΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ.) ΠœΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ функция fmap ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΈ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€, ΠΏΡ€ΠΈΠΌΠ΅Π½Ρ‘Π½Π½Ρ‹ΠΉ ΠΊ ΠΎΠ΄Π½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ, ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€, ΠΏΡ€ΠΈΠΌΠ΅Π½Ρ‘Π½Π½Ρ‹ΠΉ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.

Если это Π·Π²ΡƒΡ‡ΠΈΡ‚ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ нСпонятно, Π½Π΅ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΉΡ‚Π΅ΡΡŒ. Всё прояснится, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ рассмотрим нСсколько ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ².

Π“ΠΌ-м… Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΠΌΠ½Π΅ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ объявлСниС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fmap! Если Π²Ρ‹ Π½Π΅ Π·Π½Π°Π΅Ρ‚Π΅ сигнатуру Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ map, Π²ΠΎΡ‚ ΠΎΠ½Π°:

map :: (a –> b) –> [a] –> [b]

О, ΠΊΠ°ΠΊ интСрСсно! Ѐункция map Π±Π΅Ρ€Ρ‘Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈΠ· a Π² b ΠΈ список элСмСнтов Ρ‚ΠΈΠΏΠ° a ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ список элСмСнтов Ρ‚ΠΈΠΏΠ° b. Π”Ρ€ΡƒΠ·ΡŒΡ, ΠΌΡ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€! ЀактичСски функция map – это функция fmap, которая Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° списках. Π’ΠΎΡ‚ ΠΊΠ°ΠΊ список сдСлан экзСмпляром класса Functor:

instance Functor [] where

   fmap = map

И всё! Π—Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅, ΠΌΡ‹ Π½Π΅ пишСм instance Functor [a] where, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΈΠ· опрСдСлСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

fmap :: (a –> b) –> f a –> f b

ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ f Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ конструктором Ρ‚ΠΈΠΏΠΎΠ², ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰ΠΈΠΌ ΠΎΠ΄ΠΈΠ½ Ρ‚ΠΈΠΏ. Π’Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ [a] – это ΡƒΠΆΠ΅ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ (список элСмСнтов Ρ‚ΠΈΠΏΠ° a), Π° Π²ΠΎΡ‚ [] – это конструктор Ρ‚ΠΈΠΏΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ Ρ‚ΠΈΠΏ; ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹, ΠΊΠ°ΠΊ [Int], [String] ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ [[String]].

Π’Π°ΠΊ ΠΊΠ°ΠΊ для списков функция fmap – это просто map, Ρ‚ΠΎ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΏΡ€ΠΈ ΠΈΡ… использовании Π½Π° списках:

map :: (a –> b) –> [a] –> [b]

ghci>fmap (*2) [1..3]

[2,4,6]

ghci> map (*2) [1..3]

[2,4,6]

Π§Ρ‚ΠΎ случится, Ссли ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ map ΠΈΠ»ΠΈ fmap ΠΊ пустому списку? ΠœΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΠΎΠΏΡΡ‚ΡŒ ΠΆΠ΅ пустой список. Но функция fmap ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ пустой список Ρ‚ΠΈΠΏΠ° [a] Π² пустой список Ρ‚ΠΈΠΏΠ° [b].

ЭкзСмпляр класса Functor для Ρ‚ΠΈΠΏΠ° Maybe

Π’ΠΈΠΏΡ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ вСсти сСбя ΠΊΠ°ΠΊ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΏΠΎ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡŽ ΠΊ Π΄Ρ€ΡƒΠ³ΠΈΠΌ Ρ‚ΠΈΠΏΠ°ΠΌ, ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Π°ΠΌΠΈ. МоТно ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ списки – это ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΈ с бСсконСчным числом отсСков; всС ΠΎΠ½ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ пустыми, ΠΈΠ»ΠΈ ΠΆΠ΅ ΠΎΠ΄ΠΈΠ½ отсСк Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, Π° ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ пустыС, ΠΈΠ»ΠΈ нСсколько ΠΈΠ· Π½ΠΈΡ… Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Ρ‹. А Ρ‡Ρ‚ΠΎ Π΅Ρ‰Ρ‘ ΡƒΠΌΠ΅Π΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ²? НапримСр, Ρ‚ΠΈΠΏ Maybe. Он ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ «пустой ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΎΠΉΒ», ΠΈ Π² этом случаС ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Nothing, ΠΈΠ»ΠΈ ΠΆΠ΅ Π² Π½Ρ‘ΠΌ хранится ΠΊΠ°ΠΊΠΎΠ΅-Ρ‚ΠΎ ΠΎΠ΄Π½ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ "Π₯А-Π₯А", ΠΈ Ρ‚ΠΎΠ³Π΄Π° ΠΎΠ½ Ρ€Π°Π²Π΅Π½ Just "Π₯А-Π₯А".

Π’ΠΎΡ‚ ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ Maybe сдСлан Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€ΠΎΠΌ:

instance Functor Maybe where

   fmap f (Just x) = Just (f x)

   fmap f Nothing = Nothing

Π•Ρ‰Ρ‘ Ρ€Π°Π· ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, ΠΊΠ°ΠΊ ΠΌΡ‹ записали Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΡŽ instance Functor Maybe where вмСсто instance Functor (Maybe m) where – ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Ρ‚ΠΎΠΌΡƒ ΠΊΠ°ΠΊ ΠΌΡ‹ Π΄Π΅Π»Π°Π»ΠΈ для класса YesNo. Π€ΡƒΠ½ΠΊΡ‚ΠΎΡ€ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ конструктор Ρ‚ΠΈΠΏΠ° с ΠΎΠ΄Π½ΠΈΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ, Π½Π΅ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ. Если Π²Ρ‹ мыслСнно Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ f Π½Π° Maybe, функция fmap Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΊΠ°ΠΊ (a –> b) –> Maybe a –> Maybe b, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Ρ‚ΠΈΠΏΠ° Maybe, Ρ‡Ρ‚ΠΎ Π²ΠΏΠΎΠ»Π½Π΅ сСбя ΠΎΠΏΡ€Π°Π²Π΄Ρ‹Π²Π°Π΅Ρ‚. Но Ссли Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ f Π½Π° (Maybe m), Ρ‚ΠΎ получится (a –> b) –> Maybe m a –> Maybe m b, Ρ‡Ρ‚ΠΎ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ смысла, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ Maybe ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ‚ΠΈΠΏ-ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€.

Как Π±Ρ‹ Ρ‚ΠΎ Π½ΠΈ Π±Ρ‹Π»ΠΎ, рСализация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fmap довольно проста. Если Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° Maybe – это Nothing, возвращаСтся Nothing. Если ΠΌΡ‹ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅ΠΌ Β«ΠΏΡƒΡΡ‚ΡƒΡŽ ΠΊΠΎΡ€ΠΎΠ±ΠΊΡƒΒ», ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Β«ΠΏΡƒΡΡ‚ΡƒΡŽ ΠΊΠΎΡ€ΠΎΠ±ΠΊΡƒΒ», Ρ‡Ρ‚ΠΎ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ. Π’ΠΎΡ‡Π½ΠΎ Ρ‚Π°ΠΊ ΠΆΠ΅ функция map для пустого списка Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ пустой список. Если это Π½Π΅ пустоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π° Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡƒΠΏΠ°ΠΊΠΎΠ²Π°Π½Π½ΠΎΠ΅ Π² конструктор Just, Ρ‚ΠΎ ΠΌΡ‹ примСняСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΊ содСрТимому Just:

ghci> fmap (++ " ΠŸΠ Π˜Π’Π•Π’, Π― Π’ΠΠ£Π’Π Π˜ JUST") (Just "Π‘Π΅Ρ€ΡŒΡ‘Π·Π½Π°Ρ ΡˆΡ‚ΡƒΠΊΠ°.")

Just "Π‘Π΅Ρ€ΡŒΡ‘Π·Π½Π°Ρ ΡˆΡ‚ΡƒΠΊΠ°. ΠŸΠ Π˜Π’Π•Π’, Π― Π’ΠΠ£Π’Π Π˜ JUST"

ghci> fmap (++ " ΠŸΠ Π˜Π’Π•Π’, Π― Π’ΠΠ£Π’Π Π˜ JUST") Nothing

Nothing

ghci> fmap (*2) (Just 200)

Just 400

ghci> fmap (*2) Nothing

Nothing

Π”Π΅Ρ€Π΅Π²ΡŒΡ Ρ‚ΠΎΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€Π°ΠΌΠΈ

Π•Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ Ρ‚ΠΈΠΏ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ для Π½Π΅Π³ΠΎ экзСмпляр класса Functor, – это наш Ρ‚ΠΈΠΏ Tree. Π”Π΅Ρ€Π΅Π²ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ноль ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ Π΄Ρ€ΡƒΠ³ΠΈΡ… элСмСнтов, ΠΈ конструктор Ρ‚ΠΈΠΏΠ° Tree ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ Ρ‚ΠΈΠΏ-ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€. Если Π±Ρ‹ ΠΌΡ‹ Ρ…ΠΎΡ‚Π΅Π»ΠΈ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ fmap Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Ρ‚ΠΈΠΏΠ° Tree, Π΅Ρ‘ сигнатура выглядСла Π±Ρ‹ Ρ‚Π°ΠΊ: (a –> b) –> Tree a –> Tree b.

Для этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π°ΠΌ потрСбуСтся рСкурсия. ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ пустого Π΄Π΅Ρ€Π΅Π²Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ пустоС Π΄Π΅Ρ€Π΅Π²ΠΎ. ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ нСпустого Π΄Π΅Ρ€Π΅Π²Π° – это Π΄Π΅Ρ€Π΅Π²ΠΎ, состоящСС ΠΈΠ· Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° примСнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΊ ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΌΡƒ элСмСнту ΠΈ ΠΈΠ· ΠΏΡ€Π°Π²ΠΎΠ³ΠΎ ΠΈ Π»Π΅Π²ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Π΄Π΅Ρ€Π΅Π²ΡŒΠ΅Π², ΠΊ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Ρ‚Π°ΠΊΠΆΠ΅ Π±Ρ‹Π»ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅.

instance Functor Tree where

   fmap f EmptyTree = EmptyTree

   fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right)

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ:

ghci> fmap (*2) EmptyTree

EmptyTree

ghci> fmap (*4) (foldr treeInsert EmptyTree [5,7,3])

Node 20 (Node 12 EmptyTree EmptyTree) (Node 28 EmptyTree EmptyTree)

Π’ΠΏΡ€ΠΎΡ‡Π΅ΠΌ, Ρ‚ΡƒΡ‚ слСдуСт Π±Ρ‹Ρ‚ΡŒ Π²Π½ΠΈΠΌΠ°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ! Если Ρ‚ΠΈΠΏ Tree ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для прСдставлСния Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠ³ΠΎ Π΄Π΅Ρ€Π΅Π²Π° поиска, Ρ‚ΠΎ Π½Π΅Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ, Ρ‡Ρ‚ΠΎ Π΄Π΅Ρ€Π΅Π²ΠΎ останСтся Ρ‚Π°ΠΊΠΎΠ²Ρ‹ΠΌ послС примСнСния ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ Π΅Π³ΠΎ ΡƒΠ·Π»Ρƒ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. ΠŸΡ€ΠΎΡ…ΠΎΠ΄ ΠΏΠΎ Π΄Π΅Ρ€Π΅Π²Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ, скаТСм, negate ΠΏΡ€Π΅Π²Ρ€Π°Ρ‚ΠΈΡ‚ Π΄Π΅Ρ€Π΅Π²ΠΎ поиска Π² ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ΅ Π΄Π΅Ρ€Π΅Π²ΠΎ.

И Ρ‚ΠΈΠΏ Either являСтся Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€ΠΎΠΌ

ΠžΡ‚Π»ΠΈΡ‡Π½ΠΎ! Ну Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠ°ΠΊ насчёт Either a b? МоТно Π»ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π΅Π³ΠΎ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€ΠΎΠΌ? Класс Ρ‚ΠΈΠΏΠΎΠ² Functor Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ конструктор Ρ‚ΠΈΠΏΠΎΠ² с ΠΎΠ΄Π½ΠΈΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ, Π° Ρƒ Ρ‚ΠΈΠΏΠ° Either ΠΈΡ… Π΄Π²Π°. Π“ΠΌ-м… ΠŸΡ€ΠΈΠ΄ΡƒΠΌΠ°Π» – ΠΌΡ‹ частично ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ конструктор Either, «скормив» Π΅ΠΌΡƒ ΠΎΠ΄ΠΈΠ½ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, ΠΈ Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΎΠ½ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ ΠΎΠ΄ΠΈΠ½ свободный ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€. Π’ΠΎΡ‚ ΠΊΠ°ΠΊ для Ρ‚ΠΈΠΏΠ° Either ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½ экзСмпляр класса Functor Π² стандартных Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ…:

instance Functor (Either a) where

   fmap f (Right x) = Right (f x)

   fmap f (Left x) = Left x

Π§Ρ‚ΠΎ ΠΆΠ΅ здСсь происходит? Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· записи, ΠΌΡ‹ сдСлали экзСмпляр класса Π½Π΅ для Ρ‚ΠΈΠΏΠ° Either, Π° для Either a. Π­Ρ‚ΠΎ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Either – конструктор Ρ‚ΠΈΠΏΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π΄Π²Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°, Π° Either a – Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½. Если Π±Ρ‹ функция fmap Π±Ρ‹Π»Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Either a, сигнатура Ρ‚ΠΈΠΏΠ° выглядСла Π±Ρ‹ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

(b –> c) –> Either a b –> Either a c

ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ это Ρ‚ΠΎ ΠΆΠ΅ самоС, Ρ‡Ρ‚ΠΎ

(b –> c) –> (Either a) b –> (Either a) c

Π’ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΡ‹ выполняСм ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² конструкторС Π΄Π°Π½Π½Ρ‹Ρ… Right, Π½ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ этого Π² Left. ΠŸΠΎΡ‡Π΅ΠΌΡƒ? Вспомним, ΠΊΠ°ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½ Ρ‚ΠΈΠΏ Either a b:

data Either a b = Left a | Right b

Если ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Π½Π΅ΠΊΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΊ ΠΎΠ±Π΅ΠΈΠΌ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π°ΠΌ, ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ a ΠΈ b Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΈΠΌ ΠΈ Ρ‚Π΅ΠΌ ΠΆΠ΅ Ρ‚ΠΈΠΏΠΎΠΌ. Если ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ строку ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ строку, Ρ‚ΠΎ b Ρƒ нас – строка, Π° a – число; это Π½Π΅ сработаСт. Π’Π°ΠΊΠΆΠ΅, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ смотрСли Π½Π° Ρ‚ΠΈΠΏ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fmap для Ρ‚ΠΈΠΏΠ° Either a, Ρ‚ΠΎ Π²ΠΈΠ΄Π΅Π»ΠΈ, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π΅ измСняСтся, Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΠ·ΠΌΠ΅Π½Ρ‘Π½; ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ актуализируСтся конструктором Π΄Π°Π½Π½Ρ‹Ρ… Left.

Π—Π΄Π΅ΡΡŒ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ Π½Π°ΡˆΡƒ аналогию с ΠΊΠΎΡ€ΠΎΠ±ΠΊΠ°ΠΌΠΈ, прСдставив Ρ‡Π°ΡΡ‚ΡŒ Left ΠΊΠ°ΠΊ ΠΏΡƒΡΡ‚ΡƒΡŽ ΠΊΠΎΡ€ΠΎΠ±ΠΊΡƒ, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ сбоку записано сообщСниС ΠΎΠ± ошибкС, ΠΏΠΎΡΡΠ½ΡΡŽΡ‰Π΅Π΅, ΠΏΠΎΡ‡Π΅ΠΌΡƒ Π²Π½ΡƒΡ‚Ρ€ΠΈ пусто.

ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡ ΠΈΠ· модуля Data.Map Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ‚ΠΎΡ€ΠΎΠΌ, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ хранят (ΠΈΠ»ΠΈ Π½Π΅ хранят) значСния. Для Ρ‚ΠΈΠΏΠ° Map k v функция fmap Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ v –> v' Π½Π° ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ Ρ‚ΠΈΠΏΠ° Map k v ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° Map k v'.

ΠŸΠ Π˜ΠœΠ•Π§ΠΠΠ˜Π•. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: апостроф Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния Π² Ρ‚ΠΈΠΏΠ°Ρ… (ΠΊΠ°ΠΊ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ Π΅Π³ΠΎ ΠΈ Π² ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ). Π­Ρ‚ΠΎΡ‚ символ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для обозначСния схоТих понятий, Π½Π΅Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‰ΠΈΡ…ΡΡ Π΄Ρ€ΡƒΠ³ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³Π°.

ΠŸΠΎΠΏΡ‹Ρ‚Π°ΠΉΡ‚Π΅ΡΡŒ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Π΄ΠΎΠ³Π°Π΄Π°Ρ‚ΡŒΡΡ, ΠΊΠ°ΠΊ для Ρ‚ΠΈΠΏΠ° Map k ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½ экзСмпляр класса Functor!

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