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 fr rest <- fsm f' rs return $ xs ++ rest
You are correct that you need to use data or newtype anytime a recursive type is required.
In response to your comment here, you can implement your dup function:
dup :: (Monad m) => F m dup = F dup' where dup' xs = return ([xs, xs], F dup')
... or you can split it into two separate definitions if you want.
Please note: if you are not sure what a type signature is, just enable the NoMonomorphismRestriction extension and the compiler will not complain and will correctly output the top level type for you.
source share