Монадическое сворачивание Data.Text - PullRequest
0 голосов
/ 04 декабря 2018

Я хотел бы написать функцию

countDigits :: Text -> Either Text (Map Int Int)

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

countDigits = fmap frequencies . mapM toDigit
  where
    frequencies :: Ord a => [a] -> Map a Int
    frequencies = foldr (M.adjust (+1)) M.empty

    toDigit :: Char -> Either String Int
    toDigit c
      | isDigit c = return (ord c - ord '0')
      | otherwise = Left $ "Invalid digit " ++ show c

, но, поскольку Data.Text не Foldable, я не могу использовать mapM.

На самом деле, кажется,немного трудно преобразовать значение Data.Text в любое значение ленивого потока.( сгибы Data.Text.Strict все нетерпеливы и не монадичны, и против Data.Text.Lazy было предупреждено. Это где вы вытаскиваете conduit или pipes?

1 Ответ

0 голосов
/ 04 декабря 2018

Text не может быть Traversable, поскольку он не параметризован с типом своих элементов - он всегда содержит Char s и ничего больше.Другими словами, это «мономорфный контейнер» вместо полиморфного.

Для «мономорфных контейнеров» мы имеем MonoTraversable, что обеспечивает omapM:

omapM :: Applicative m => (Element mono -> m (Element mono)) -> mono -> m mono 

, что в случае Text означает

omapM :: Applicative m => (Char -> m Char) -> Text -> m Text
...