Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8677641
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T20:30:49+00:00 2026-06-12T20:30:49+00:00

I wanted to make a generic function that folds over a wide range of

  • 0

I wanted to make a generic function that folds over a wide range of inputs (see Making a single function work on lists, ByteStrings and Texts (and perhaps other similar representations)). As one answer suggested, the ListLike is just for that. Its FoldableLL class defines an abstraction for anything that is foldable. However, I need a monadic fold. So I need to define foldM in terms of foldl/foldr.

So far, my attempts failed. I tried to define

foldM'' :: (Monad m, LL.FoldableLL full a) => (b -> a -> m b) -> b -> full -> m b
foldM'' f z = LL.foldl (\acc x -> acc >>= (`f` x)) (return z)

but it runs out of memory on large inputs – it builds a large unevaluated tree of computations. For example, if I pass a large text file to

main :: IO ()
main = getContents >>= foldM'' idx 0 >> return ()
  where
    -- print the current index if 'a' is found
    idx !i 'a' = print i >> return (i + 1)
    idx !i _   =            return (i + 1)

it eats up all memory and fails.

I have a feeling that the problem is that the monadic computations are composed in a wrong order – like ((... >>= ...) >>= ...) instead of (... >>= (... >>= ...)) but so far I didn’t find out how to fix it.


Workaround: Since ListLike exposes mapM_, I constructed foldM on ListLikes by wrapping the accumulator into the state monad:

modifyT :: (Monad m) => (s -> m s) -> StateT s m ()
modifyT f = get >>= \x -> lift (f x) >>= put

foldLLM :: (LL.ListLike full a, Monad m) => (b -> a -> m b) -> b -> full -> m b
foldLLM f z c = execStateT (LL.mapM_ (\x -> modifyT (\b -> f b x)) c) z

While this works fine on large data sets, it’s not very nice. And it doesn’t answer the original question, if it’s possible to define it on data that are just FoldableLL (without mapM_).

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T20:30:50+00:00Added an answer on June 12, 2026 at 8:30 pm

    So the goal is to reimplement foldM using either foldr or foldl. Which one should it be? We want the input to be processed lazily and allow for infinte lists, this rules out foldl. So foldr is it going to be.

    So here is the definition of foldM from the standard library.

    foldM             :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
    foldM _ a []      =  return a
    foldM f a (x:xs)  =  f a x >>= \fax -> foldM f fax xs
    

    The thing to remember about foldr is that its arguments simply replace [] and : in the list (ListLike abstracts over that, but it still serves as a guiding principle).

    So what should [] be replaced with? Clearly with return a. But where does a come from? It won’t be the initial a that is passed to foldM – if the list is not empty, when foldr reaches the end of the list, the accumulator should have changed. So we replace [] by a function that takes an accumulator and returns it in the underlying monad: \a -> return a (or simply return). This also gives the type of the thing that foldr will calculate: a -> m a.

    And what should we replace : with? It needs to be a function b -> (a -> m a) -> (a -> m a), taking the first element of the list, the processed tail (lazily, of course) and the current accumulator. We can figure it out by taking hints from the code above: It is going to be \x rest a -> f a x >>= rest. So our implementation of foldM will be (adjusting the type variables to match them in the code above):

    foldM'' :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
    foldM'' f z list = foldr (\x rest a -> f a x >>= rest) return list z
    

    And indeed, now your program can consume arbitrary large input, spitting out the results as you go.

    We can even prove, inductively, that the definitions are semantically equal (although we should probably do coinduction or take-induction to cater for infinite lists).

    We want to show

    foldM f a xs = foldM'' f a xs
    

    for all xs :: [b]. For xs = [] we have

      foldM f a []
    ≡ return a     -- definition of foldM
    ≡ foldr (\x rest a -> f a x >>= rest) return [] a -- definition of foldr
    ≡ foldM'' f a [] -- definition of foldM''
    

    and, assuming we have it for xs, we show it for x:xs:

      foldM f a (x:xs)
    ≡ f a x >>= \fax -> foldM f fax xs --definition of foldM
    ≡ f a x >>= \fax -> foldM'' f fax xs -- induction hypothesis
    ≡ f a x >>= \fax -> foldr (\x rest a -> f a x >>= rest) return xs fax -- definition of foldM''
    ≡ f a x >>= foldr (\x rest a -> f a x >>= rest) return xs -- eta expansion
    ≡ foldr (\x rest a -> f a x >>= rest) return (x:xs) -- definition of foldr
    ≡ foldM'' f a (x:xs) -- definition of foldM''
    

    Of course this equational reasoning does not tell you anything about the performance properties you were interested in.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I wanted to make a function that populates a Grid in WPF with pictures.
I wanted to make an application that will take either the path of the
I wanted to make a button which is transparent until the user hovers over
I'm trying to create a generic function that removes duplicates from an std::vector. Since
I'm starting to consider creating a class library that I want to make generic
How could I make this code more generic in the sense that the Dictionary
As an exercise I'm trying to create a function that returns a generic list
I'm creating a custom control and wanted to make it generic enough to use
I wanted some guidance if possible on how to make this more generic: def
I am attempting to make a form that takes user inputs for first name

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.