.
Например, в школе есть шкафчики для того, чтобы ученикам было куда клеить постеры Guns’n’Roses. Каждый шкафчик открывается кодовой комбинацией. Если школьнику понадобился шкафчик, он говорит администратору, шкафчик под каким номером ему нравится, и администратор выдаёт ему код. Если этот шкафчик уже кем-либо используется, администратор не сообщает код – они вместе с учеником должны будут выбрать другой вариант. Будем использовать модуль >Data.Map
для того, чтобы хранить информацию о шкафчиках. Это будет отображение из номера шкафчика в пару, где первый компонент указывает, используется шкафчик или нет, а второй компонент – код шкафчика.
>import qualified Data.Map as Map
>data LockerState = Taken | Free deriving (Show, Eq)
>type Code = String
>type LockerMap = Map.Map Int (LockerState, Code)
Довольно просто. Мы объявляем новый тип данных для хранения информации о том, был шкафчик занят или нет. Также мы создаём синоним для кода шкафчика и для типа, который отображает целые числа в пары из статуса шкафчика и кода. Теперь создадим функцию для поиска кода по номеру. Мы будем использовать тип >Either String Code
для представления результата, так как поиск может не удаться по двум причинам – шкафчик уже занят, в этом случае нельзя сообщать код, или номер шкафчика не найден вообще. Если поиск не удался, возвращаем значение типа >String
с пояснениями.
>lockerLookup :: Int –> LockerMap –> Either String Code
>lockerLookup lockerNumber map =
> case Map.lookup lockerNumber map of
> Nothing –> Left $ "Шкафчик № " ++ show lockerNumber ++
> " не существует!"
> Just (state, code) –>
> if state /= Taken
> then Right code
> else Left $ "Шкафчик № " ++ show lockerNumber ++ " уже занят!"
Мы делаем обычный поиск по отображению. Если мы получили значение >Nothing
, то вернём значение типа >Left String
, говорящее, что такой номер не существует. Если мы нашли номер, делаем дополнительную проверку, занят ли шкафчик. Если он занят, возвращаем значение >Left
, говорящее, что шкафчик занят. Если он не занят, возвращаем значение типа >Right Code
, в котором даём студенту код шкафчика. На самом деле это >Right String
, но мы создали синоним типа, чтобы сделать наши объявления более понятными. Вот пример отображения:
>lockers :: LockerMap lockers = Map.fromList
> [(100,(Taken,"ZD39I"))
> ,(101,(Free,"JAH3I"))
> ,(103,(Free,"IQSA9"))
> ,(105,(Free,"QOTSA"))
> ,(109,(Taken,"893JJ"))
> ,(110,(Taken,"99292"))
> ]
Давайте попытаемся узнать несколько кодов.
>ghci> lockerLookup 101 lockers
>Right "JAH3I"