6

I'm trying to get the code below working. It's a finite state machine where I pass in a function-as-next-state. The function is called with r and returns a list of results + the next function-as-next state. Keep on calling until the list runs out, and return the concatenation of the results. The monad is an error monad to allow me to throw an error if needed.

fsm f []     = return []
fsm f (r:rs) = do
    (xs, f') <- f r
    rest     <- fsm f' rs
    return $ xs ++ rest

The error is:

Occurs check: cannot construct the infinite type: t1 = t0 -> m0 ([a0], t1)
In the first argument of `fsm', namely f'

I've seen the infinite type error before and I understand the way around it is to wrap a type with a newtype. But I cannot figure out how to get this done.

Can someone point out the insight?

2
  • 1
    WHat is the type of f? Can you write it down?
    – Ingo
    Commented Mar 18, 2013 at 23:46
  • It would be f :: String -> m ([String], t) where t would be the type of f. I understand this is why it is an infinite type but cannot figure out how to wrap it up correctly.
    – me2
    Commented Mar 18, 2013 at 23:50

1 Answer 1

5

I think this is what you want:

newtype F m = F { unF :: String -> m ([String], F m) }

fsm :: (Monad m) => F m -> [String] -> m [String]
fsm f []     = return []
fsm f (r:rs) = do
    (xs, f') <- unF f r
    rest     <- fsm f' rs
    return $ xs ++ rest

You are right that you need to use a data or newtype any time you want a recursive type.

In reply to your comment, here's how you would implement your dup function:

dup :: (Monad m) => F m
dup = F dup' where dup' xs = return ([xs, xs], F dup')

... or you could split it up into two separate definitions if you prefer.

Note that if you are not sure what the type signature should be, just enable the NoMonomorphismRestriction extension and the compiler will not complain and correctly infer the top-level type for you.

2
  • Hi Gabriel -- sorry, thought I could carry on, but I'm stuck again. Tried a simple f: dup' xs = return ([xs, xs], FSM dup'). Works. Then when I tried dup = FSM dup' so that I can feed it into fsm, it gives me a monomorphism error. What am I missing now?
    – me2
    Commented Mar 19, 2013 at 0:33
  • Don't worry! I updated my question showing you how to implement your dup function. Commented Mar 19, 2013 at 0:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.