user4035
user4035

Reputation: 23749

Using id inside do notation

I am watching a Haskell online course, Reader monad chapter. The instructor gives the following example: this function takes a list and returns Nothing if it's empty or (Just head) otherwise.

safeHead = do
  -- argument is implicit here
  b <- null
  if b then
    return Nothing
  else do
    h <- head
    return $ Just h

safeHead' = do
  e <- id -- the error
  if (null e)
    then Nothing
    else return $ Just (head e)

The second function takes the list explicitly, using e <- id. But, unfortunately, it doesn't work for me. ghci gives an error:

• Couldn't match expected type ‘Maybe [a]’
              with actual type ‘a0 -> a0’
 • Probable cause: ‘id’ is applied to too few arguments
    In a stmt of a 'do' block: e <- id
    In the expression:
      do e <- id
         if (null e) then Nothing else return $ Just (head e)

This example was probably tested by the authors 3 years ago, when the course was created (or maybe, it was wrong from the beginning).

I have a suspicion that null takes a wrapped value, while id doesn't:

Prelude> :t null
null :: Foldable t => t a -> Bool
Prelude> :t id
id :: a -> a

What's wrong and how to fix?

Upvotes: 0

Views: 74

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 51074

Actually, you just forgot a return. The following works fine:

safeHead' = do
  e <- id
  if (null e)
    then return Nothing         -- need return here
    else return $ Just (head e)

or you can factor the return out:

safeHead' = do
  e <- id
  return $ if (null e)
    then Nothing
    else Just (head e)

Upvotes: 6

Related Questions