I\'ve got the following, which type-checks:
p_int = liftA read (many (char \' \') *> many1 digit <* many (char \' \'))
Now, as the fu
p_int is a parser that produces an Int, so the type would be Parser Int or similar¹.
p_int = liftA read (many (char ' ') *> many1 digit <* many (char ' ')) :: Parser Int
Alternatively, you can type the read function, (read :: String -> Int) to tell the compiler which type the expression has.
p_int = liftA (read :: String -> Int) (many (char ' ') *> many1 digit <* many (char ' ')) :: Int
As for the cleaner ways, consider replacing many (char ' ') with spaces.
¹ ParsecT x y z Int, for example.