Data.Text 的单次折叠
Monadic folding of Data.Text
我想写一个函数
countDigits :: Text -> Either Text (Map Int Int)
构建数字字符的直方图,如果存在非数字字符并带有指示第一个或所有非数字字符的消息,则会失败。如果这是 String
我可以写类似
countDigits = fmap frequencies . mapM toDigit
where
frequencies :: Ord a => [a] -> Map a Int
frequencies = M.fromListWith (+) . (`zip` [0..9])
toDigit :: Char -> Either String Int
toDigit c = readEither [c] <> Left ("Invalid digit " ++ show c)
但由于 Data.Text
不是 Foldable
,我无法使用 mapM
。
事实上,将Data.Text
值转换为任何惰性流值似乎有点困难。 (folds of Data.Text.Strict
都是 eager 和 non-monadic,并且 Data.Text.Lazy
已被警告。这是拉出 conduit
或 pipes
的地方吗?
Text
不能是 Traversable
因为它没有用它的元素类型参数化——它总是包含 Char
,没有别的。换句话说,它是一个"monomorphic container"而不是一个多态的。
对于 "monomorphic containers" 我们有 MonoTraversable
提供 omapM
:
omapM :: Applicative m => (Element mono -> m (Element mono)) -> mono -> m mono
这意味着,在 Text
的情况下,
omapM :: Applicative m => (Char -> m Char) -> Text -> m Text
我想写一个函数
countDigits :: Text -> Either Text (Map Int Int)
构建数字字符的直方图,如果存在非数字字符并带有指示第一个或所有非数字字符的消息,则会失败。如果这是 String
我可以写类似
countDigits = fmap frequencies . mapM toDigit
where
frequencies :: Ord a => [a] -> Map a Int
frequencies = M.fromListWith (+) . (`zip` [0..9])
toDigit :: Char -> Either String Int
toDigit c = readEither [c] <> Left ("Invalid digit " ++ show c)
但由于 Data.Text
不是 Foldable
,我无法使用 mapM
。
事实上,将Data.Text
值转换为任何惰性流值似乎有点困难。 (folds of Data.Text.Strict
都是 eager 和 non-monadic,并且 Data.Text.Lazy
已被警告。这是拉出 conduit
或 pipes
的地方吗?
Text
不能是 Traversable
因为它没有用它的元素类型参数化——它总是包含 Char
,没有别的。换句话说,它是一个"monomorphic container"而不是一个多态的。
对于 "monomorphic containers" 我们有 MonoTraversable
提供 omapM
:
omapM :: Applicative m => (Element mono -> m (Element mono)) -> mono -> m mono
这意味着,在 Text
的情况下,
omapM :: Applicative m => (Char -> m Char) -> Text -> m Text