-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add foldlM' #543
Add foldlM' #543
Conversation
As suggested in comments (was it @thomasjm asking?), the simplest solution is But yes, |
I tried that: encodeMethod :: Text -> VS.Vector Char
encodeMethod t =
case encodeUtf32LE t of
BS ptr len ->
runST $ VS.unsafeFreeze $
VSM.unsafeFromForeignPtr0 (castForeignPtr ptr) (len `quot` 4))) But it requires reaching into internal parts of the bytestring library* and more importantly it wasn't efficient:
* I guess perhaps I could use |
src/Data/Text.hs
Outdated
@@ -1070,6 +1071,11 @@ foldl1' :: HasCallStack => (Char -> Char -> Char) -> Text -> Char | |||
foldl1' f t = S.foldl1' f (stream t) | |||
{-# INLINE foldl1' #-} | |||
|
|||
-- | /O(n)/ A monadic version of 'foldl'. | |||
foldlM :: Monad m => (a -> Char -> m a) -> a -> Text -> m a | |||
foldlM f z t = S.foldlM f z (stream t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this implementation match Data.Foldable.foldlM
, especially with regards to short-circuiting and the order of effects? Would be nice to have a test, at least for m ~ Maybe
and m ~ Either
.
Sigh. |
Whoa, thanks for doing this @noughtmare! Yes, that was me asking on StackOverflow :) |
I just found out that we can define foldlM k z t = T.foldr (\x go s -> k s x >>= go) pure t z This optimizes to a tight loop. |
I added some tests and rebased. To answer some of the questions:
We could but we don't need to. Because of Specializing
Idk about an actual benchmark, but I added an inspection test that the simplified Core is the same as
What you defined is actually already Given that the lazy I have no clue about the
Both the direct implementation and the Although it's a one-liner with |
@Lysxia looks good to me, thanks for wrapping it up. Could you please fix the CI job with |
Fixed by inspection-testing |
Thanks all! |
I haven't added tests or benchmarks yet, because I'm not quite sure how to do it.
Open questions:
foldlM'
?Data.Text.Internal.Fusion.Common
folds markedINLINE [0]
?For motivation, see this recent stackoverflow question. There the problem is to convert a text into a vector of characters, but that requires extraneous allocation if done naively with
unfoldr Text.uncons
. If afoldlM
function were exposed like I implemented in this PR then you can write it efficiently like this:Benchmark results:
This matches the performance of an implementation I wrote that loops over the internal stream representation manually.