I’ve been working through the CIS 194 Haskell course (https://www.seas.upenn.edu/~cis1940/spring13/lectures.html) and have gotten stuck on HW 10. I haven’t been able to find a solution online. Any help would be appreciated!
The Parser is provided:
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
In addition, the HW provides satisfy, char, and posInt:
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where
f [] = Nothing -- fail on the empty input
f (x:xs) -- check if x satisfies the predicate
-- if so, return x along with the remainder
-- of the input (that is, xs)
| p x = Just (x, xs)
| otherwise = Nothing -- otherwise, fail
char :: Char -> Parser Char
char c = satisfy (== c)
osInt :: Parser Integer
posInt = Parser f
where
f xs
| null ns = Nothing
| otherwise = Just (read ns, rest)
where (ns, rest) = span isDigit XS
Following along in the homework I’ve defined the following for questions 1-4:
instance Functor Parser where
fmap :: (a -> b) -> Parser a -> Parser b
fmap f parser = Parser (inString -> case runParser parser inString of
Nothing -> Nothing
Just (result, rest) -> Just (f result, rest))
instance Applicative Parser where
pure f = Parser (input -> Just (f, input))
pa <*> pb = Parser (input -> case runParser pa input of
Nothing -> Nothing
Just (f, rest) -> runParser (f <$> pb) rest)
abParser :: Parser (Char, Char)
abParser = (,) <$> char 'a' <*> char 'b'
abParser_ :: Parser ()
abParser_ = const () <$ char 'a' <*> char 'b'
intPair :: Parser (Integer, Integer)
intPair = selector <$> posInt <*> char ' ' <*> posInt where
selector x y z = (x, z)
instance Alternative Parser where
empty :: Parser a
empty = Parser f where f _ = Nothing
(<|>) :: Parser a -> Parser a -> Parser a
(<|>) pa pb = Parser (inputString -> runParser pa inputString <|> runParser pb inputString)
So far, all of this has worked as expected, but I’m now stuck on Exercise 5:
Blockquote
Implement a parser
intOrUppercase :: Parser ()
which parses either an integer value or an uppercase character, and fails otherwise.
cis 194: homework 10 4
*Parser> runParser intOrUppercase "342abcd"
Just ((), "abcd")
*Parser> runParser intOrUppercase "XYZ"
Just ((), "YZ")
*Parser> runParser intOrUppercase "foo"
Nothing
My initial attempt was this:
intOrUppercase :: Parser ()
intOrUppercase = Parser (inputString -> (satisfy isUpper inputString) <|> (posInt inputString))
However, I get an error because of the type mismatch; the left Parser is Char and the right Parser is Integer, so this violates (<|>) :: Parser a -> Parser a -> Parser a
How can I implement the intOrUppercase Parser without violating this? Did I mess up somewhere else, or am I going about intOrUppercase the wrong way?