Trouble explaining Haskell code with where and pattern match - haskell

I have hard time parsing how mf m y are assigned values or even why there can be 3 variables on the left side of assignment in where section.
Q: Can anyone explain what happens here in both cases? (that is for empty list and a list with some elements)
-- | A variant of 'foldl' that has no base case,
-- and thus may only be applied to non-empty structures.
--
-- #'foldl1' f = 'List.foldl1' f . 'toList'#
foldl1 :: (a -> a -> a) -> t a -> a
foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")
(foldl mf Nothing xs)
where
mf m y = Just (case m of
Nothing -> y
Just x -> f x y)
(this is the source code for the foldl1 function).

Definitions in where clauses follow the same syntax as global definitions, so mf m y = ... defines a function named mf, which takes parameters named m and y.

I have hard time parsing how mf m y are assigned values or even why there can be 3 variables.
You do not define three variables here: you define a variable mf which is a function, and m and y are two arguments of the function mf.
We can make the function more elegant, and thus omit the m and y. mf can be defined as:
mf Nothing = Just . id
mf (Just x) = Just . f x
Mind that we can not simply make mf an outer function, since it uses a function f, with is a parameter of foldl1. So we put it in a where clause:
foldl1 :: (a -> a -> a) -> t a -> a
foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")
(foldl mf Nothing xs)
where mf Nothing = Just . id
mf (Just x) = Just . f x

In the empty list case, foldl mf Nothing [] ~ Nothing by definition, so foldl1 will return the "empty structure" error.
When xs is not empty, then foldl1' is simply a left fold by foldl. In this case foldl has the type
foldl :: (Maybe a -> a -> Maybe a) -> Maybe a -> [a] -> Maybe a
which makes use of the combining function mf :: Maybe a -> a -> Maybe a defined in the where clause.

Related

Map then filter in Haskell

I want to Map an Integer type list in Haskell, and then if the map function returns Nothing I want to discard the result. The function I am trying to write will have a type signature of
mapThenFilter :: (Integer -> Maybe Integer) -> [Integer] -> [Integer]
and so far, I have thought of doing this:
checkIfNothing value = case value of
Just a -> a
Nothing -> 0
mapThenFilter = map checkIfNothing(map f l)
But this is incorrect. I am new to Haskell, so if possible can you advise me on where I am going wrong here? I believe since this is Map then Filter, the Haskell filter function is probably expected to be used too, however, I believe the outer map function in my function definition is doing the job intended(of the filter function)right?
As stated in the comments you are reimplementing mapMaybe.
Which is good. It is a non-obvious function, and it is good that you feel the need for it and came up with that idea, expressed in its type.
If you'd like to do it your way, you were off to a good start actually. Need to tweak it though:
checkIfNothing value = case value of
Just a -> a
Nothing -> 0
0 is too specific, let's go with []. But now simply returning a won't work. Let's put it in a list, too:
checkIfNothing :: Maybe t -> [t]
checkIfNothing value = case value of
Just a -> [a]
Nothing -> []
So that now,
mapThenFilter f l = map checkIfNothing (map f l)
is almost right. We produce our results in lists, and those that were skipped result in empty lists:
-- instead of
[ a, b, c, .... , z ]
-- we produce
[ [], [b], [], .... , [z] ]
and so we just need to concatenate them, to join them together with ++s:
[]++[b]++[]++...,++[z]
[ b, ...., z ]
And so we define
mapThenFilter :: (a1 -> Maybe a) -> [a1] -> [a]
mapThenFilter f l = concat $ map checkIfNothing (map f l)
By the way checkIfNothing also already exists. It is known as maybeToList:
> foo f l = concat $ map maybeToList $ map f l
foo :: (a1 -> Maybe a) -> [a1] -> [a]
> foo (\x -> listToMaybe [x | even x]) [1..10]
[2,4,6,8,10]
A combination of concat and map is important enough to have a special function assigned to do its job, concatMap. And that function is important enough to even be assigned a special operator, to do its job:
foo f = concat . map maybeToList . map f
= concat . map (maybeToList . f)
= concatMap (maybeToList . f)
= (maybeToList . f =<<)

How can i fix this higher order function code in haskell?

I want to fix this code
h :: (a -> b) -> [a] -> [b]
h f = foldr (\x y -> f x : y) []
if i put h (+100) [1,2,3,4,5] in GHCI
it returns to me [101,202,303,404,505]
when i put h (*10) [1,2,3,4,5] then
i want to get [10,200,3000,40000,500000] list
can anyone help me fixing this code?
You here implemented a map, but in order to repeat the same operation multiple times, you need to perform a mapping on the tail y:
h :: (a -> a) -> [a] -> [a]
h f = foldr (\x y -> f x : map f y) []
Solving the general problem, as Willem Van Onsem's answer does, requires O(n^2) time to calculate the first n elements, because the function has to be applied k times to calculate the kth element.
To solve this sort of problem efficiently, you will need to take advantage of some additional structure. Based on your examples, I think the most obvious approach is to think about semigroup actions. That is, instead of applying an arbitrary function repeatedly, look for an efficient way to represent the compositions of the function. For example, (*x) can be represented by x, allowing (*x) . (*y) to be represented by x*y.
To apply this idea, we first need to transform Willem's solution to make the compositions explicit.
h :: (a -> a) -> [a] -> [a]
h f0 as0 = go as0 f0
where
go [] _ = []
go (a:as) f = f a : go as (f0 . f)
If we like, we can write that as a fold:
h :: (a -> a) -> [a] -> [a]
h f0 as = foldr go stop as f0
where
stop _ = []
go a r f = f a : r (f0 . f)
Now we've structured the function using an accumulator (which is a function). As we compose onto the accumulator, it will get slower and slower to apply it. We want to replace that accumulator with one we can "apply" quickly.
{-# language BangPatterns #-}
import Data.Semigroup
repeatedly :: Semigroup s => (s -> a -> a) -> s -> [a] -> [a]
repeatedly act s0 as = foldr go stop as s0
where
stop _ = []
go a r !s = act s a : r (s0 <> s)
Now you can use, for example,
repeatedly (\(Product s) -> (s*)) (Product 10) [1..5]
==> [10,200,3000,40000,500000]
repeatedly (\(Sum s) -> (s+)) (Sum 100) [1..5]
==> [101,202,303,404,505]
In each of these, you accumulate a product/sum which is added to/multiplied by the current list element.

Can this function be written in point-free style? If not, why?

One related question is this, but some of the answer say that almost anything can be made point free, so what is wrong with this function?
\[x] -> x
http://pointfree.io/ doesn't seem to be able to write it in point-free style. Does this mean that it cannot be written that way? If so, what is the theoretical reason for it?
I can only observe that the function above is a "crippled" version of head (or last, fwiw) which can only operate on singleton lists. Indeed, applied on non singleton lists, it errors this way in ghci:
*** Exception: <interactive>:380:5-13: Non-exhaustive patterns in lambda
Maybe the "non-exhaustivity" on the pattern is the reason why some functions cannot be written in point-free style?
Edit in the light of the answers:
I did not expect that the answers to my question could be so complex (I feel I just thought that the short answer was no, it cannot, actually), so I need to find some time to read them carefully, experiment a bit, and wrap my mind around them, otherwise I cannot decide which one should be accepted. For the time being, +1 to Jon Purdy's answer, which I could easily understand up to This is where I would stop in ordinary code.
Well, a data type isn't a function. As long as your function isn't unwrapping any data values (i.e. it's just shuffling them between functions/constructors), you can write it point free, but there's simply no syntax for point free matching. However, you only ever need one non-point-free function per data type: the fold. In Haskell, data types are pretty much defined by their folds. Taking the folds of the relevant data types as primitives, you can rewrite any function point free. Note that there are actually several possible "folds". For [a], the recursive one (which comes from the Church/Böhm-Berarducci encoding) is foldr :: (a -> b -> b) -> b -> [a] -> b. Another possible fold is the "case-but-it's-a-function" one, (a -> [a] -> b) -> b -> [a] -> b, which comes from the Scott encoding (recursion can then be recovered with fix, which is another "pointful pointfree primitive"), but, as #SilvioMayolo notes, there isn't such a function in the standard library. Either would do, but we don't have the latter predefined so let's just use foldr.
\[x] -> x
can be written
fst . foldr (\x f -> (snd f x, \_ -> error "got (_ : _ : _) wanted [x]")) (error "got [] wanted [x]", id)
-- I don't care enough to replicate the exact exceptions.
-- this is "flattened" from
let fold [] = (error "got [] wanted [x]", id)
fold (x : xs) = (snd (fold xs) x, \_ -> error "got (_ : _ : _) wanted [x]")
in fst . fold
fold returns a pair, basically (what to return if this was the entire list, how to transform the head if it wasn't). For [], we want to return an error if that was the entire list, but otherwise pass through the element right before we hit []. For x : xs, if there is an element preceding it, we want to ignore it and return an error, and if there isn't, we want to pass it to snd (fold xs), which checks if xs = [] or else gives an error. We've eliminated all matches, so just shove this through pointfree.io to get the \x f -> _ in the argument to foldr out:
behead = fst . foldr (flip flip (const (error "got (_ : _ : _) wanted [x]")) . ((,) .) . flip snd) (error "got [] wanted [x]", id)
ghci> :t behead
behead :: Foldable t => t c -> c
ghci> behead []
*** Exception: got [] wanted [x]
ghci> behead [1]
1
ghci> behead [1, 2]
*** Exception: got (_ : _ : _) wanted [x]
ghci> behead [1..]
*** Exception: got (_ : _ : _) wanted [x]
Lovely.
Note: a previous version of this answer used an "inlined" auxiliary data type, basically because it just "came to me" as I was writing it. However, it failed to handle infinite lists properly (behead [1..] would hang). This version uses the built in pairs as the auxiliary data type, which have sufficient library support that I don't have to inline them to make it pointfree. It is slightly harder to inline (,), thereby eliminating the pointfullness inside the implementations of fst and snd, but it is still possible, using this newtype:
newtype Pair a b = Pair { unPair :: forall r. (a -> b -> r) -> r }
Alternatively, cheat on the types a bit and use this:
-- residual pointfullness can be reduced by pointfree.io
\xs -> foldr (\x r f -> f (r (const id) x) (\_ -> error "got (_ : _ : _) wanted [x]")) (\f -> f (error "got [] wanted [x]") id) xs (\x _ _ -> x) undefined
Sure, pretty much anything can be made pointfree. The tricky thing is what functions you'll allow in the resulting expression. If we pattern match, we generally need a fold function to do the matching instead. So, for instance, if we pattern matched on a Maybe a, we'd need to replace that with maybe. Similarly, Either a b patterns can be written in terms of either.
Note the pattern in the signatures
data Maybe a = Nothing | Just a
maybe :: b -> (a -> b) -> (Maybe a -> b)
Maybe a has two constructors, one which takes no arguments and the other which takes an a. So maybe takes two arguments: one which is a 0-ary function (b), and one which takes an a (a -> b), and then returns a function from Maybe a -> b. The same pattern is present in either
data Either a b = Left a | Right b
either :: (a -> c) -> (b -> c) -> (Either a b -> c)
Two cases. The first takes an a and produces whatever c we want. The second takes a b and produces whatever c we want. In every case, we want one function for each possible term in the sum type.
In order to systematically pointfree a function like \[x] -> x, we'd need a similar fold. [a] is declared as, essentially
data [a] = [] | a : [a]
So we'd need a function with this signature
list :: b -> (a -> [a] -> b) -> ([a] -> b)
Now, flip foldr comes close
flip foldr :: b -> (a -> b -> b) -> ([a] -> b)
But it's recursive. It calls its provided function on the [a] part of a : [a]. We want a true fold, which isn't provided by Haskell's base libraries. A quick Hoogle search tells us that this function does exist in a package though, called extra. Of course, for this small example we can just write it ourselves very easily.
list :: b -> (a -> [a] -> b) -> ([a] -> b)
list f g x = case x of
[] -> f
(y:ys) -> g y ys
Now we can apply it to your \[x] -> x easily. First, let's write what your function really does, including all of the messy undefined cases (I'll use undefined rather than a long error message here, for brevity)
func :: [a] -> a
func x = case x of
[] -> undefined
(y:ys) -> case ys of
[] -> y
(_:_) -> undefined
Now every case statement exactly matches each constructor once. This is ripe for transformation into a fold.
func :: [a] -> a
func x = case x of
[] -> undefined
(y:ys) -> list y undefined ys
And now we transform the outer case as well
func :: [a] -> a
func x = list undefined (\y -> list y undefined) x
So we have
func :: [a] -> a
func = list undefined (\y -> list y undefined)
Or, if we want to be truly crazy about it
func :: [a] -> a
func = list undefined (flip list undefined)
But this function isn't in base
Yeah, that's true. We kind of cheated by using a fold that didn't exist. If we want to do it systematically, we need that fold operator. But without it, we can still kludge it together with foldr1, which suffices for our particular purposes.
func' :: [a] -> a
func' = foldr1 (const (const undefined))
So, to answer your question, we can't always systematically replace pattern matching like in your example with pointfree, unless we have a fold function with the right signature. Fortunately, that function can always be written, for any Haskell 98 data type (possibly GADTs as well, but I haven't considered that possibility in any depth). But even without that support, we can still make it work, kind of.
A simple way to write this in pointfree form is to use a fold, where the accumulator state is one of the following:
Empty: We haven’t seen an element yet; keep it
Full: We have seen an element; raise an error
If the final state is Empty, we also raise an error. This accumulator can be represented naturally with Maybe:
fromSingleton :: (Foldable t) => t a -> a
fromSingleton
= fromMaybe (error "empty list")
. foldr (flip maybe (error "plural list") . Just) Nothing
This is where I would stop in ordinary code. But…
If you don’t want to use an auxiliary data type, you can get rid of the Maybe by representing it with Böhm–Berarducci encoding:
type Maybe' r a
= r -- ‘Nothing’ continuation
-> (a -> r) -- ‘Just’ continuation
-> r -- Result
just' :: a -> Maybe' r a
-- just' = \ x _n j -> j x
just'
= const -- Ignore ‘Nothing’ continuation
. flip ($) -- Apply ‘Just’ continuation to value
nothing' :: Maybe' r a
-- nothing' = \ n _j -> n
nothing' = const -- Ignore ‘Just’ continuation
maybe' :: r -> (a -> r) -> Maybe' r a -> r
-- maybe' = \ n j k -> k n j
maybe'
= flip -- Apply to ‘Just’ continuation
. flip ($) -- Apply to ‘Nothing’ continuation
fromMaybe' :: r -> Maybe' r r -> r
-- fromMaybe' = \ n k -> k n id
fromMaybe' = flip maybe' id -- Pass ‘id’ as ‘Just’ continuation
However, we can’t just do a wholesale replacement of Just with just', maybe with maybe', and so on; the types won’t work out:
> :t fromMaybe' (error "empty list") . foldr (flip maybe' (error "plural list") . just') nothing'
<interactive>:…:…: error:
• Occurs check: cannot construct the infinite type: c ~ Maybe' c c
Expected type: c -> Maybe' c c -> Maybe' c c
Actual type: c -> Maybe' (Maybe' c c) c -> Maybe' c c
• In the first argument of ‘foldr’, namely
‘(flip maybe' (error "plural list") . just')’
In the second argument of ‘(.)’, namely
‘foldr (flip maybe' (error "plural list") . just') nothing'’
In the expression:
fromMaybe' (error "empty list")
. foldr (flip maybe' (error "plural list") . just') nothing'
The problem is that we’re returning a Maybe' from a Maybe' continuation, and the compiler is trying to unify the two result types. One solution is to first eta-expand to let the typechecker know where we want to construct a distinct function:
> :t fromMaybe' (error "empty list") . foldr (\ x acc -> \ n j -> maybe' (just' x n j) (error "plural list") acc) nothing'
fromMaybe' (error "empty list") . foldr (\ x acc -> \ n j -> maybe' (just' x n j) (error "plural list") acc) nothing'
:: Foldable t => t c -> c
Then we can incrementally rewrite to pointfree form:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(\ x acc
-> \ n j
-> maybe'
(just' x n j)
(error "plural list")
acc)
nothing'
-- Move ‘n’ & ‘j’ past ‘error …’ with ‘flip’:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(\ x acc
-> \ n j
-> flip maybe'
----
(error "plural list")
(just' x n j)
acc)
nothing'
-- Move ‘n’ & ‘j’ past ‘acc’ with ‘flip’ again:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(\ x acc
-> \ n j
-> flip (flip maybe' (error "plural list")) acc
----
(just' x n j))
nothing'
-- Eta-reduce ‘j’ with composition:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(\ x acc
-> \ n
-> flip (flip maybe' (error "plural list")) acc
. just' x n)
--
nothing'
-- Eta-reduce ‘n’ with ‘fmap’ (to map “under” an argument):
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(\ x acc
-> fmap (flip (flip maybe' (error "plural list")) acc)
----
. just' x)
nothing'
-- Move ‘x’ rightward with ‘flip’ on the outside:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(flip (\ acc x
----
-> fmap (flip (flip maybe' (error "plural list")) acc)
. just' x))
nothing'
-- Replace composition with ‘fmap’:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(flip (\ acc x
-> fmap (fmap (flip (flip maybe' (error "plural list")) acc))
----
(just' x)))
nothing'
-- Eta-reduce ‘x’ with composition:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(flip (\ acc
-> fmap (fmap (flip (flip maybe' (error "plural list")) acc))
. just'))
--
nothing'
-- Replace composition with ‘fmap’:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(flip (\ acc
-> fmap (fmap (fmap (flip (flip maybe' (error "plural list")) acc)))
----
just'))
nothing'
-- Move ‘acc’ rightward with ‘flip’:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(flip (\ acc
-> flip fmap just'
----
(fmap (fmap (flip (flip maybe' (error "plural list")) acc)))))
nothing'
-- Eta-reduce with composition:
fromSingleton
= fromMaybe' (error "empty list")
. foldr
(flip
(flip fmap just'
. fmap . fmap . flip (flip maybe' (error "plural list"))))
-- - -
nothing'
This is fully pointfree as well (far less readable than our original code, but better than what pointfree generates). In fact it’s good practice in pointfree code to use many small auxiliary definitions like fromMaybe' instead of inlining everything, but we can proceed to inline their definitions.
However, you can’t inline them naïvely and get exactly the same type—if you do, you’ll arrive at (Foldable t) => t (a -> b) -> a -> b. It could be a good exercise to work through where you need to eta-expand and rewrite in order to obtain the expected type, (Foldable t) => t a -> a.

Haskell- function that accepts a list of functions

I need to write a function that accepts a list of functions, and a value, as parameters. Every function in the list must be applied, in turn, on the value.
For example, if my function is called compFuncs...
compFuncs [f,g,h] val equivalent to f(g(h val))
I can already tell that using a foldr would be useful here, I can put the . operator between each function in the list of functions and then apply it to val. However, I can't complete it, this is my attempt...
compFuncs :: [(a->a->a)] -> a -> a
compFuncs [] val = val
compFuncs (x:xs) val = foldr //Im lost here
Can someone help me out?
(I believe you intended to write the type as composeFuncs :: [a -> a] -> a -> a as this is how it is used.)
foldr works by replacing the constructors of a list with the replacements you specify. For example, foldr (+) 0 [1,2,3] works by taking the list [1,2,3], which is really constructed as 1:2:3:[], and replacing (:) with (+) and [] with 0 as follows:
1 : 2 : 3 : []
1 + 2 + 3 + 0
If you think about a list of functions [f,g,h] that you want to apply to some value as \x -> f (g (h x)), we can find a foldr by looking for replacements for (:) and []. First, let's use composition:
\x -> f (g (h x))
= (definition of (.))
\x -> (f . g . h) x
= (eta reduction)
f . g . h
This is close, but we must do something with the empty list constructor. We need to replace it with some sort of "do nothing" or "empty" function. Luckily, we have id, which is guaranteed not to change the result in any way:
f . g . h
= (definition of id)
f . g . h . id
Now we can see the fold:
f . g . h . id
f : g : h : []
and we write it as:
composeFuncs :: [a -> a] -> a -> a
composeFuncs = foldr (.) id
By the way, types that can be folded like this with an element that functions as an "identity" are known as monoids*, and a -> a is the Endo monoid.
* There is an additional requirement that the function used to combine values, like (.) for Endo or (+) for Sum, is associative. You'll notice that this allowed me to present them without needing parenthesis above.
Edit
For another way to discover this function, let's use GHC 7.8's new typed holes feature. First, we start with a definition of composeFuncs with some holes:
composeFuncs :: [a -> a] -> a -> a
composeFuncs = foldr _f _z
When GHC type checks this we get a type error, which I will reduce to the relevent lines:
tmp.hs:6:22: Found hole ‘_f’ with type: (a -> a) -> (a -> a) -> a -> a …
tmp.hs:6:25: Found hole ‘_z’ with type: a -> a …
Starting with _z, there is only one possible function of type a -> a, and that's id. For _f, we need a function that combines two functions to give a new function. That is, of course, (.), so we write:
composeFuncs :: [a -> a] -> a -> a
composeFuncs = foldr (.) id

How to define foldM using foldr/foldl (if it is possible)?

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_).
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.

Resources