Trouble explaining Haskell code with where and pattern match

Viewed 69

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

3 Answers

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