Карты Haskell, возвращающие монаду - PullRequest
10 голосов
/ 13 июня 2010

Функция поиска в Data.Map и Data.IntMap в настоящее время возвращает значения, заключенные в Maybe с тип подписи

lookup  :: Ord  k => k -> Map  k a -> Maybe  a

Раньше имел более общий тип

lookup  :: (Monad  m, Ord  k) => k -> Map  k a -> m a

Я понимаю, что первое, вероятно, уменьшает потребность в дополнительной спецификации типа, но последнее сделает его гораздо более общим и позволит использовать поиск в списках. Есть ли способ имитировать это поведение с более новой версией, или мне придется использовать более старую версию библиотеки?

Ответы [ 3 ]

19 голосов
/ 13 июня 2010

последнее сделало бы его гораздо более общим и позволило бы использовать поиск в списках

Последний также более небезопасен, так как большинство классов монад определяют сбой как error. То есть, общий случай не нахождения элемента на карте - это ошибка завершения программы для большинства монад. Это, в сочетании с повышенной вероятностью неверного вывода контекста типа, означает, что сейчас мы склонны препятствовать стилю «монадический возврат при неудаче».

Есть ли способ имитировать это поведение с более новой версией

Действительно, есть! Просто поднимите Maybe a в Monad a, вот так:

lift :: Monad m => Maybe a -> m a
lift Nothing  = fail "you die now"
lift (Just a) = return a

А теперь вы можете написать, например, lift . lookup

5 голосов
/ 13 июня 2010

Don's lift преобразует Maybe элементы в их общие Monad аналоги, поэтому, возможно, его следует назвать convert или generalize или что-то еще; -)

Если вы просто хотите использовать lookup в основном в списках и других монадах, которые реализуют fail, вы также можете использовать отображение сбоя сопоставления с шаблоном на fail:

Prelude> [ v | Just v <- return $ lookup "hi" [("ho","silver")] ]
[]
Prelude> [ v | Just v <- return $ lookup "ho" [("ho","silver")] ]
["silver"]

Prelude> do Just v <- return $ lookup "hi" [("ho","silver")] ; print v
*** Exception: user error (Pattern match failure in do expression at <interactive>:1:3-8)
Prelude> do Just v <- return $ lookup "ho" [("ho","silver")] ; print v
"silver"
4 голосов
/ 13 июня 2010

Для конкретного случая монады списка самое простое решение - использовать 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"]
...