I’m trying the codes from <Real World Haskell>.
On GHC version 6.10.4:
data ParseState = ParseState {
string :: String
} deriving (Show)
newtype Parse a = Parse {
runParse :: ParseState -> Either String (a, ParseState)
}
parse :: Parse a -> String -> Either String a
parse parser initState =
case runParse parser (ParseState initState) of
Left err -> Left err
Right (result, _) -> Right result
Everything went fine until I changed ‘Left err’ to ‘err@(Left _)’:
-- err@(Left _) -> err
{-
- Occurs check: cannot construct the infinite type:
- a = (a, ParseState)
- When generalising the type(s) for `parse'
-}
Any ideas?
This is subtle. The
caseis scrutinizing a value of typeEither String (a, ParseState), so when you name the pattern inerrhas that same type. However, the function’s return type says it should be anEither String a, which doesn’t matcherr‘s type ofEither String (a, ParseState). Looking at the type ofLeft:When you use
Leftin the right-hand side inYou are giving it a chance to choose a different
y, namelyainstead of(a, ParseState).So even though the values are the same, the types are not, and so they can’t be substituted.
By the way, there are a few very handy functions for your case in
Control.Arrow(specializing to(->)for simplicity):whose semantics are fixed by the free theorems (read: they only have one reasonable implementation, so they do what you’d expect from their types). So you could write your code as: