Home > Uncategorized > Some code kata – haskell while loops

Some code kata – haskell while loops

In the previous post we solved the following problem using a for loop

Write three functions that compute the sum of the numbers in a given list using a for-loop, a while-loop, and recursion.

I have not found while loop primitives in the standard library but a library for this exists on hackage and it is called Control.Monad.Loops. It provides the following implementation

whileM_ :: (Monad m) => m Bool -> m a -> m ()
whileM_ p f = go
  where go = do
           x <- p
           if x
           then f >> go
           else return ()

Looking at the type signature we see that it takes a bool wrapped in a monad as a first argument and another monad which is the action as a second argument. The result, as with the for loop, is a monad containing nothing (or more correct the unit value).

Again, since we want to do stateful programming we will turn to the State monad. This time we need to keep both the remaining list and the sum within the state. A tuple seems like a natural choice.

The most complicated part is the condition. We use the get function to retrieve the current state. The get function has the following type signature

get :: MonadState s m => m s

It simply returns the state as a value wrapped within the monad. However, we want to test wether the list is empty or not. fmap or the equivalent applicative functor <$> is a function that allow us to apply an ordinary function to the value wrapped within the monad – transforming it to something else which in this case should be a boolean value indicating whether we should continue looping or not.

This is the type signature for fmap and <$> respectivly

(<$>) :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> f a -> f b

To test whether the list is empty we can then do the following (assuming that the list is stored as the first element in the state tuple)

not . null . fst <$> get

The final result, when putting this together, may look like below

import Control.Monad
import Control.Monad.State

whileM_ p f = go
  where go = do
    x <- p
    if x
    then f >> go
    else return ()

sumUsingWhile xs = snd $ execState loop (xs,0)
  where
    loop = whileM_ (not . null . fst <$> get) $
             modify $ \(x:xs,sum) -> (xs, x+sum)

 

Advertisements
Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: