Карты Haskell возвращают монад
Вопрос
Функция поиска в data.map и data.intmap в настоящее время возвращает значения, обернутые, возможно, с помощью подписи типа
lookup :: Ord k => k -> Map k a -> Maybe a
Раньше было более общего типа
lookup :: (Monad m, Ord k) => k -> Map k a -> m a
Я понимаю, что скорее всего, скорее всего снижает необходимость спецификации дополнительных типов, но последний сделает его гораздо более общее и позволить поиску использовать в представлениях списка. Есть ли способ подражать этому поведению с новой версией, или я должен был бы использовать более старую версию библиотеки?
Решение
Дон lift
преобразует Maybe
элементы их общему Monad
коллеги, так что, возможно, это должно быть названо convert
или generalize
или что-то;-)
Если вы просто хотите использовать lookup
в основном в поручении списка и другие монады, которые реализуют fail
, вы также можете использовать отображение сбоя спинки шаблона fail
:
Прелюдия> [V | Просто V <- Return $ lookup "Привет" [("HO", "Silver")]] [] Prelude> [V | Просто V <- Return $ lookup "Ho" [("Ho", "Silver")]] [«Серебро»] Прелюдия> Просто V <- Return $ lookup "Привет" [("HO", "Silver") ]; Print v *** Исключение: ошибка пользователя (сбой спинки шаблона в выраженииu003Cinteractive> : 1: 3-8) Прелюдия> Просто V <- Return $ lookup "Ho" [("Ho", "Silver")]; Печать V "Silver"
Другие советы
Последнее сделало бы намного более общее и позволить поиску использовать в состав списка
Последнее также более небезопасно, так как большинство классов монад определяют неудачу, как error
. Отказ То есть общий случай не найти элемент на карте - это ошибка, завершающая программа для большинства монадских. Что, в сочетании с повышенной вероятностью неправильного типа контекста.
Есть ли способ имитировать это поведение с новой версией
Действительно, есть! Просто поднимите, может быть, A в Монаде А, вроде так:
lift :: Monad m => Maybe a -> m a
lift Nothing = fail "you die now"
lift (Just a) = return a
И теперь вы можете написать, например, lift . lookup
Для конкретного случая списка монады простейшее решение должно использовать maybeToList
:
Prelude> :m +Data.Maybe -- Note: Use "import Data.Maybe" in a program file
Data.Maybe> [ v | v <- maybeToList $ lookup "hi" [("ho","silver")] ]
[]
Data.Maybe> [ v | v <- maybeToList $ lookup "ho" [("ho","silver")] ]
["silver"]