Изучай Haskell во имя добра! (Липовача) - страница 75

>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]. Сначала напишем функцию, конвертирующую телефонный номер в строке в список целых. Можно попытаться применить функцию