Gergely
Gergely

Reputation: 7525

Sequencing actions in Haskell

I have the following code from Hutton's Programming in Haskell, second edition, page 12:

seqn [] = return []
seqn (act:acts) = do x  <- act
                     xs <- seqn acts
                     return (x::xs)

For this, ghci tells me that

seqn.hs:4:30: error:
    • Couldn't match expected type ‘xs’ with actual type ‘a’
      ‘xs’ is a rigid type variable bound by
        an expression type signature:
          forall xs. xs
        at seqn.hs:4:33-34
      ‘a’ is a rigid type variable bound by
        the inferred type of seqn :: Monad m => [m a] -> m [a1]
        at seqn.hs:(1,1)-(4,35)
    • In the first argument of ‘return’, namely ‘(x :: xs)’
      In a stmt of a 'do' block: return (x :: xs)
      In the expression:
        do x <- act
           xs <- seqn acts
           return (x :: xs)
    • Relevant bindings include
        x :: a (bound at seqn.hs:2:22)
        acts :: [m a] (bound at seqn.hs:2:11)
        act :: m a (bound at seqn.hs:2:7)
        seqn :: [m a] -> m [a1] (bound at seqn.hs:1:1)
  |
4 |                      return (x::xs)
  |                              ^
Failed, no modules loaded.

What am I missing here?

Upvotes: 0

Views: 85

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477503

It is probably a typo, either in the course or by yourself. It should be:

seqn [] = return []
seqn (act : acts) = do
  x <- act
  xs <- seqn acts
  return (x : xs)

Some folks prefer to avoid binding names (like x and xs) unnecessarily. We can remove xs:

seqn [] = return []
seqn (act : acts) = do
  x <- act
  (x :) <$> seqn acts

and further remove x as well:

seqn [] = return []
seqn (act : acts) = (:) <$> act <*> seqn acts

The :: is used to specify types, whereas (:) :: a -> [a] -> [a] is a data constructor for lists.

Upvotes: 2

Related Questions