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

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

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

findKey :: (Eq k) => k –> [(k,v)] –> Maybe v

findKey key [] = Nothing

findKey key ((k,v):xs)

  | key == k = Just v

  | otherwise = findKey key xs

ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π° Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΡŽ Ρ‚ΠΈΠΏΠ°. Ѐункция ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΊΠ»ΡŽΡ‡, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π½Π° равСнство (Eq), ΠΈ ассоциативный список, Π° Π·Π°Ρ‚Π΅ΠΌ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Выглядит ΠΏΡ€Π°Π²Π΄ΠΎΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ.

Π­Ρ‚ΠΎ классичСская рСкурсивная функция, ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‰Π°Ρ список. Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ случай, Ρ€Π°Π·Π±ΠΈΠ΅Π½ΠΈΠ΅ списка Π½Π° Β«Π³ΠΎΠ»ΠΎΠ²ΡƒΒ» ΠΈ «хвост», рСкурсивный Π²Ρ‹Π·ΠΎΠ² – всё Π½Π° мСстС. Π’Π°ΠΊΠΆΠ΅ это классичСский шаблон для примСнСния свёртки. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ, ΠΊΠ°ΠΊ Ρ‚ΠΎ ΠΆΠ΅ самоС ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ свёртки.

findKey :: (Eq k) => k –> [(k,v)] –> Maybe v

findKey key = foldr (\(k,v) acc –> if key == k then Just v else acc) Nothing

ΠŸΠ Π˜ΠœΠ•Π§ΠΠΠ˜Π•. Как ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свёртки для ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… стандартных рСкурсивных ΠΎΠ±Ρ…ΠΎΠ΄ΠΎΠ² списка вмСсто явного описания рСкурсивной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ свёртки Π»Π΅Π³Ρ‡Π΅ Ρ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ΠΈ ΠΏΠΎΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ. Π›ΡŽΠ±ΠΎΠΉ Ρ‡Π΅Π»ΠΎΠ²Π΅ΠΊ догадаСтся, Ρ‡Ρ‚ΠΎ это свёртка, ΠΊΠ°ΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ foldr – ΠΎΠ΄Π½Π°ΠΊΠΎ потрСбуСтся большС ΠΈΠ½Ρ‚Π΅Π»Π»Π΅ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… усилий для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°ΡΠΏΠΎΠ·Π½Π°Ρ‚ΡŒ явно Π½Π°ΠΏΠΈΡΠ°Π½Π½ΡƒΡŽ Ρ€Π΅ΠΊΡƒΡ€ΡΠΈΡŽ.

ghci> findKey "юля" phoneBook

Just "853–24-92"

ghci> findKey "оля" phoneBook

Just "555–29-38"

ghci> findKey "аня" phoneBook

Nothing

ΠžΡ‚Π»ΠΈΡ‡Π½ΠΎ, Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚! Если Ρƒ нас Π΅ΡΡ‚ΡŒ Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½Ρ‹ΠΉ Π½ΠΎΠΌΠ΅Ρ€ Π΄Π΅Π²ΡƒΡˆΠΊΠΈ, ΠΌΡ‹ просто (Just) ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π½ΠΎΠΌΠ΅Ρ€; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π½ΠΈΡ‡Π΅Π³ΠΎ (Nothing).

ΠœΠΎΠ΄ΡƒΠ»ΡŒ Data.Map


ΠœΡ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ lookup ΠΈΠ· модуля Data.List. Если Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ ΠΊΠ»ΡŽΡ‡Ρƒ, понадобится ΠΎΠ±ΠΎΠΉΡ‚ΠΈ всС элСмСнты списка, ΠΏΠΎΠΊΠ° ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ Π½Π°ΠΉΠ΄Ρ‘ΠΌ.

ΠœΠΎΠ΄ΡƒΠ»ΡŒ Data.Map ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ ассоциативныС списки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π½Π°ΠΌΠ½ΠΎΠ³ΠΎ быстрСС (ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π΄Π΅Ρ€Π΅Π²ΡŒΠ΅Π²), Π° Ρ‚Π°ΠΊΠΆΠ΅ мноТСство Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ. Начиная с этого ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅ΠΌ с отобраТСниями вмСсто ассоциативных списков.

Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Data.Map экспортируСт Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΡƒΡŽΡ‰ΠΈΠ΅ с модулями Prelude ΠΈ Data.List, ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ²Π°Π»ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΈΠΌΠΏΠΎΡ€Ρ‚Π°.

import qualified Data.Map as Map

ΠŸΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅ этот ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ Π² исходный ΠΊΠΎΠ΄ ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚Π΅ Π΅Π³ΠΎ Π² GHCi. ΠœΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ ассоциативный список Π² ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fromList ΠΈΠ· модуля Data.Map. Ѐункция fromList ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ассоциативный список (Π² Ρ„ΠΎΡ€ΠΌΠ΅ списка) ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с Ρ‚Π΅ΠΌΠΈ ΠΆΠ΅ ассоциациями. НСмного ΠΏΠΎΠΈΠ³Ρ€Π°Π΅ΠΌ:

ghci> Map.fromList [(3, "Ρ‚ΡƒΡ„Π»ΠΈ"),(4,"Π΄Π΅Ρ€Π΅Π²ΡŒΡ"),(9,"ΠΏΡ‡Ρ‘Π»Ρ‹")]

fromList [(3, "Ρ‚ΡƒΡ„Π»ΠΈ"),(4,"Π΄Π΅Ρ€Π΅Π²ΡŒΡ"),(9,"ΠΏΡ‡Ρ‘Π»Ρ‹")]

ghci> Map.fromList [("эрик","Ρ„ΠΎΡ€ΠΌΠ°Π½"),("Ρ€ΠΎΠ±Π΅Ρ€Ρ‚","Ρ‡Π΅ΠΉΠ·"),("крис", "Ρ‚Π°ΡƒΠ±")]

fromList [("крис","Ρ‚Π°ΡƒΠ±"),("Ρ€ΠΎΠ±Π΅Ρ€Ρ‚","Ρ‡Π΅ΠΉΠ·"),("эрик","Ρ„ΠΎΡ€ΠΌΠ°Π½")]

Когда ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠ· модуля Data.Map показываСтся Π² консоли, сначала выводится fromList, Π° Π·Π°Ρ‚Π΅ΠΌ ассоциативный список, ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅.

Если Π² исходном спискС Π΅ΡΡ‚ΡŒ Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚Ρ‹ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ, ΠΎΠ½ΠΈ ΠΎΡ‚Π±Ρ€Π°ΡΡ‹Π²Π°ΡŽΡ‚ΡΡ:

ghci> Map.fromList [("MS",1),("MS",2),("MS",3)]

fromList [("MS",3)]

Π’ΠΎΡ‚ сигнатура Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fromList:

Map.fromList :: (Ord k) => [(k, v)] –> Map.Map k v

Она Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚, Ρ‡Ρ‚ΠΎ функция ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ список ΠΏΠ°Ρ€ со значСниями Ρ‚ΠΈΠΏΠ° k ΠΈ v ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ ΠΊΠ»ΡŽΡ‡ΠΈ Ρ‚ΠΈΠΏΠ° k Π² значСния Ρ‚ΠΈΠΏΠ° v. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Ссли ΠΌΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ ассоциативный список с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ списка, Ρ‚ΠΎ значСния ΠΊΠ»ΡŽΡ‡Π΅ΠΉ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ лишь ΡƒΠΌΠ΅Ρ‚ΡŒ ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒΡΡ (ΠΈΠΌΠ΅Ρ‚ΡŒ экзСмпляр класса Ρ‚ΠΈΠΏΠΎΠ² Eq); Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈΡ… ΡƒΠΏΠΎΡ€ΡΠ΄ΠΎΡ‡ΠΈΡ‚ΡŒ (класс Ρ‚ΠΈΠΏΠΎΠ² Ord). Π­Ρ‚ΠΎ сущСствСнноС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ модуля Data.Map. УпорядочиваСмыС ΠΊΠ»ΡŽΡ‡ΠΈ Π½ΡƒΠΆΠ½Ρ‹ Π΅ΠΌΡƒ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π±ΠΎΠ»Π΅Π΅ эффСктивно.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ наш исходный ассоциативный список phoneBook Π² ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅. Π—Π°ΠΎΠ΄Π½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ сигнатуру:

import qualified Data.Map as Map


phoneBook :: Map.Map String String

phoneBook = Map.fromList $

  [("оля","555–29-38")

  ,("ТСня","452–29-28")

  ,("катя","493–29-28")

  ,("маша","205–29-28")

  ,("надя","939–82-82")

  ,("юля","853–24-92")

  ]

ΠžΡ‚Π»ΠΈΡ‡Π½ΠΎ. Π—Π°Π³Ρ€ΡƒΠ·ΠΈΠΌ этот сцСнарий Π² GHCi ΠΈ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΈΠ³Ρ€Π°Π΅ΠΌ с Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½ΠΎΠΉ ΠΊΠ½ΠΈΠΆΠΊΠΎΠΉ. Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ lookup ΠΈ ΠΏΠΎΠΈΡ‰Π΅ΠΌ ΠΊΠ°ΠΊΠΈΠ΅-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π½ΠΎΠΌΠ΅Ρ€Π°. Ѐункция lookup ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΊΠ»ΡŽΡ‡ ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ пытаСтся Π½Π°ΠΉΡ‚ΠΈ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ ΠΊΠ»ΡŽΡ‡Ρƒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Если всё ΠΏΡ€ΠΎΡˆΠ»ΠΎ ΡƒΠ΄Π°Ρ‡Π½ΠΎ, возвращаСтся ΠΎΠ±Ρ‘Ρ€Π½ΡƒΡ‚ΠΎΠ΅ Π² Just Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС – Nothing:

ghci> :t Map.lookup

Map.lookup :: (Ord k) => k -> Map.Map k a -> Maybe a

ghci> Map.lookup "оля" phoneBook

Just "555-29-38"

ghci> Map.lookup "надя" phoneBook

Just "939-82-82"

ghci> Map.lookup "таня" phoneBook

Nothing

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ‚Ρ€ΡŽΠΊ: создадим Π½ΠΎΠ²ΠΎΠ΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, Π΄ΠΎΠ±Π°Π²ΠΈΠ² Π² исходноС Π½ΠΎΠ²Ρ‹ΠΉ Π½ΠΎΠΌΠ΅Ρ€. Ѐункция insert ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΊΠ»ΡŽΡ‡, Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ – ΠΏΠΎΡ‡Ρ‚ΠΈ Ρ‚Π°ΠΊΠΎΠ΅ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΈ исходноС, Π½ΠΎ с Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½Ρ‹ΠΌΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠΌ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ:

ghci> :t Map.insert

Map.insert :: (Ord k) => k -> a -> Map.Map k a -> Map.Map k a

ghci> Map.lookup "таня" phoneBook

Nothing

ghci> let newBook = Map.insert "таня" "341-90-21" phoneBook

ghci> Map.lookup "таня" newBook

Just "341-90-21"

Π”Π°Π²Π°ΠΉΡ‚Π΅ посчитаСм, сколько Ρƒ нас Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½Ρ‹Ρ… Π½ΠΎΠΌΠ΅Ρ€ΠΎΠ². Для этого Π½Π°ΠΌ понадобится функция size ΠΈΠ· модуля Data.Map. Она ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π΅Π³ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€. Π’ΡƒΡ‚ всё ясно:

ghci> :t Map.size

Map.size :: Map.Map k a -> Int

ghci> Map.size phoneBook

6

ghci> Map.size newBook

7



НомСра Π² нашСй Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½ΠΎΠΉ ΠΊΠ½ΠΈΠΆΠΊΠ΅ прСдставлСны строками. Допустим, ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ вмСсто Π½ΠΈΡ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ списки Ρ†ΠΈΡ„Ρ€: Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ вмСсто Π½ΠΎΠΌΠ΅Ρ€Π° "939-82-82" – список [9,3,9,8,2,8,2]. Π‘Π½Π°Ρ‡Π°Π»Π° напишСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‰ΡƒΡŽ Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½Ρ‹ΠΉ Π½ΠΎΠΌΠ΅Ρ€ Π² строкС Π² список Ρ†Π΅Π»Ρ‹Ρ…. МоТно ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ digitToInt ΠΈΠ· модуля Data.Char ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ символу Π² строкС, Π½ΠΎ ΠΎΠ½Π° Π½Π΅ Π·Π½Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ с дСфисом! ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·Π±Π°Π²ΠΈΡ‚ΡŒΡΡ ΠΎΡ‚ всСх Π½Π΅Ρ†ΠΈΡ„Ρ€. ΠŸΠΎΠΏΡ€ΠΎΡΠΈΠΌ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ isDigit ΠΈΠ· модуля Data.Char, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ символ ΠΈ сообщаСт Π½Π°ΠΌ, являСтся Π»ΠΈ ΠΎΠ½ Ρ†ΠΈΡ„Ρ€ΠΎΠΉ. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ строка Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Π½Π°, пройдёмся ΠΏΠΎ Π½Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ digitToInt.

string2digits :: String -> [Int]

string2digits = map digitToInt . filter isDigit

Π”Π°, Π½Π΅ Π·Π°Π±ΡƒΠ΄ΡŒΡ‚Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Data.Char. ΠŸΡ€ΠΎΠ±ΡƒΠ΅ΠΌ:

ghci> string2digits "948-92-82"

[9,4,8,9,2,8,2]

Π—Π°ΠΌΠ΅Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ! Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ map ΠΈΠ· модуля Data. Map, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ string2digits ΠΏΠΎ элСмСнтам отобраТСния phoneBook:

ghci> let intBook = Map.Map string2digits phoneBook

ghci> :t intBook

intBook :: Map.Map String [Int]

ghci> Map.lookup "оля" intBook

Just [5,5,5,2,9,3,8]

Ѐункция map ΠΈΠ· модуля Data.Map ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ примСняСт эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ Π² ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ.

Π Π°ΡΡˆΠΈΡ€ΠΈΠΌ Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½ΡƒΡŽ ΠΊΠ½ΠΈΠΆΠΊΡƒ. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ ΠΊΠΎΠ³ΠΎ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π΅ΡΡ‚ΡŒ нСсколько Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π½Ρ‹Ρ… Π½ΠΎΠΌΠ΅Ρ€ΠΎΠ², ΠΈ наш ассоциативный список выглядит ΠΊΠ°ΠΊ-Ρ‚ΠΎ Ρ‚Π°ΠΊ:

phoneBook =

  [("оля","555–29-38")

  ,("оля","342–24-92")

  ,("ТСня","452–29-28")

  ,("катя","493–29-28")

  ,("катя","943–29-29")

  ,("катя","827–91-62")

  ,("маша","205–29-28")

  ,("надя","939–82-82")

  ,("юля","853–24-92")

  ,("юля","555–21-11")

  ]

Если ΠΌΡ‹ просто Π²Ρ‹Π·ΠΎΠ²Π΅ΠΌ fromList, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ всё это Π² ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, Ρ‚ΠΎ потСряСм массу Π½ΠΎΠΌΠ΅Ρ€ΠΎΠ²! ВмСсто этого Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ ΠΈΠ· модуля Data.Map, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ fromListWith. Π­Ρ‚Π° функция дСйствуСт ΠΏΠΎΡ‡Ρ‚ΠΈ ΠΊΠ°ΠΊ fromList, Π½ΠΎ вмСсто отбрасывания ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡŽΡ‰ΠΈΡ…ΡΡ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΡƒΡŽ Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая ΠΈ Ρ€Π΅ΡˆΠ°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ.

phoneBookToMap :: (Ord k) => [(k, String)] -> Map.Map k String

phoneBookToMap xs = Map.fromListWith add xs

  where add number1 number2 = number1 ++ ", " ++ number2

Если функция fromListWith ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΊΠ»ΡŽΡ‡ ΡƒΠΆΠ΅ сущСствуСт, ΠΎΠ½Π° Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΡƒΡŽ Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая соСдиняСт ΠΎΠ±Π° значСния Π² ΠΎΠ΄Π½ΠΎ, Π° Π·Π°Ρ‚Π΅ΠΌ замСняСт староС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π° Π½ΠΎΠ²ΠΎΠ΅, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ ΠΎΡ‚ ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

ghci> Map.lookup "катя" $ phoneBookToMap phoneBook

"827–91-62, 943–29-29, 493–29-28"

ghci> Map.lookup "надя" $ phoneBookToMap phoneBook

"939-82-82"

ghci> Map.lookup "оля" $ phoneBookToMap phoneBook

"342-24-92, 555-29-38"

А Π΅Ρ‰Ρ‘ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ всС значСния Π² ассоциативном спискС одноэлСмСнтными списками, Π° ΠΏΠΎΡ‚ΠΎΠΌ ΡΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ ++, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

phoneBookToMap :: (Ord k) => [(k, a)] -> Map.Map k [a]

phoneBookToMap xs = Map.fromListWith (++) $ map (\(k,v) -> (k, [v])) xs

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

ghci> Map.lookup "катя" $ phoneBookToMap phoneBook

["827–91-62","943–29-29","493–29-28"]