Haskell Parse string of Ints to tuple (Int,Int) - parsing

I would like to parse a string in form 3 3 from input user to a tuple (3,3) is this possible?
stringtup :: String -> Maybe (Int, Int)
stringtup s = do
[(n, [c])] <- return $ reads s
return (n, c)
this is my attempt but it does't work..

reads only parses one value (if possible), and gives it back as well as the rest of the input string. So,
[(n, _)] <- return $ reads s
works and will, for "3 3" indeed have n≡3.
But the other number still needs to be parsed too. So what you'd actually do is first bind something like
[(n, s')] <- return $ reads s
and then parse the other number in the same fashion from s'.

Related

Taking a parser in argument and try to apply it zero or more times

I am currently writing a basic parser. A parser for type a takes a string in argument and returns either nothing, or an object of type a and the rest of the string.
Here is a simple type satisfying all these features:
type Parser a = String -> Maybe (a, String)
For example, I wrote a function that takes a Char as argument and returns a Parser Char :
parseChar :: Char -> Parser Char
parseChar _ [] = Nothing
parseChar c (x:xs)
| c == x = Just (x, xs)
| otherwise = Nothing
I would like to write a function which takes a parser in argument and tries to apply it zero or more times, returning a list of the parsed elements :
parse :: Parser a -> Parser [a]
Usage example:
> parse (parseChar ' ') " foobar"
Just (" ", "foobar")
I tried to write a recursive function but I can't save the parsed elements in a list.
How can I apply the parsing several times and save the result in a list ?
I tried to write a recursive function but I can't save the parsed elements in a list.
You don't need to "save" anything. You can use pattern matching. Here's a hint. Try to reason about what should happen in each case below. The middle case is a bit subtle, don't worry if you get that wrong at first. Note how s and s' are used below.
parse :: Parser a -> Parser [a]
parse p s = case p s of
Nothing -> ... -- first p failed
Just (x,s') -> case parse p s' of
Nothing -> ... -- subtle case, might not be relevant after all
Just (xs,s'') -> ... -- merge the results
Another hint: note that according to your description parse p should never fail, since it can always return the empty list.

Unpacking nested applicative functors f#

Hi I am attempting to make a combinator parser and I am currently attempting to make it read headers and create parsers based upon what the header which is parsed is. I.e A header of; int, float, string will result in Parser<Parser<int>*Parser<float>*Parser<string>>.
I am wondering however how you would unpack the "inner" parsers which and then end up with a something like; Parser<int*float*string>?
Parser type is: type Parser<'a> = Parser of (string -> Result<'a * string, string>)
I'm not sure that your idea with nested parsers is going to work - if you parse a header dynamically, then you'll need to produce a list of parsers of the same type. The way you wrote this is suggesting that the type of the parser will depend on the input, which is not possible in F#.
So, I'd expect that you will need to define a value like this:
type Value = Int of int | String of string | Float of float
And then your parser that parses a header will produce something like:
let parseHeaders args : Parser<Parser<Value> list> = (...)
The next question is, what do you want to do with the nested parsers? Presumably, you'll need to turn them into a single parser that parses the whole line of data (if this is something like a CSV file). Typically, you'd define a function sequence:
val sequence : sep:Parser<unit> -> parsers:Parser<'a> list -> Parser<'a list>
This takes a separator (say, parser to recognize a comma) and a list of parsers and produces a single parser that runs all the parsers in a sequence with the separator in between.
Then you can do:
parseHeaders input |> map (fun parsers -> sequence (char ',') parsers)
And you get a single parser Parser<Parser<string>>. You now want to run the nested parser on the rest of the that is left after running the outer parser, which recognizes headers. The following function does the trick:
let unwrap (Parser f:Parser<Parser<'a>>) = Parser (fun s ->
match f s with
| Result.Ok(Parser nested, rest) -> nested rest
| Result.Error e -> Result.Error e )

When can there be an ambiguous parse using reads?

The Standard Haskell Classes page says the following about reads :: (Read a) => String -> [(a,String)]:
Normally, a parser returns a singleton list, containing a value of
type a that was read from the input string and the remaining string
that follows what was parsed. If no parse was possible, however, the
result is the empty list, and if there is more than one possible parse
(an ambiguity), the resulting list contains more than one pair.
Under what situations or examples does this ambiguity manifest?
import Text.Read
data Foo = Bar Int | Baz Double deriving Show
instance Read Foo where
readPrec = fmap Bar readPrec +++ fmap Baz readPrec
In this example, the parser tries to parse Int and Double. If it can be parsed for both, the parser returns two values.
Resulting in:
> read "4" :: Foo
*** Exception: Prelude.read: ambiguous parse
and
> reads "4" :: [(Foo,String)]
[(Bar 4,""),(Baz 4.0,"")]
The easiest way here to fix ambiguity is to select one parse by replacing the choice operator +++ with the selective choice <++.

How to read in an Int and use it in another function

I am trying to read in an Int and then use the read value in a pure function, but it does not seem to work properly. After searching through a lot of resources I use the from here.
So my code goes as the following:
main = do
putStrLn "Please input a number."
inputjar <- getLine
return (read inputjar :: Int)
Which works fine, but when I want to use it in my pure function:
usrSetBrick :: [[Int]] -> [[Int]]
usrSetBrick xs = setBrick (main) (main) (main) xs
I get a compile error:
Couldn't match expected type `Int' with actual type `IO Int'
In the first argument of `setBrick', namely `(main)'
In the expression: setBrick (main) (main) (main) xs
In an equation for `usrSetBrick':
usrSetBrick xs = setBrick (tull) (tull) (tull) xs
Failed, modules loaded: none.
So from what I understand does main return an int. Even it should, as I can understand from
return (read inputjar :: Int)
How can I make the read input usable in my function?
You probably don't want to be using main to return things since it's the entry point to your program. Instead, you can write a function
getInt :: IO Int
getInt = do
input <- getLine
return (read input) -- Don't have to specify Int here, GHC can figure it out from the type signature
However, your function setBrick, which presumably has the type Int -> Int -> Int -> [[Int]] -> [[Int]], can't use getInt directly. This is by design, Haskell's type system forces you to treat IO actions separately from pure functions (once you get used to it, it's a wonderful tool for reasoning about your code). Instead, you can do something like
promptInt :: IO Int
promptInt = do
putStrLn "Please input a number."
getInt
usrSetBrick :: [[Int]] -> IO [[Int]]
usrSetBrick xs = do
a <- promptInt
b <- promptInt
c <- promptInt
return $ setBrick a b c xs
The types Int and IO Int are not the same in Haskell, you can not use the interchangeably. This holds true for types like [Int], Maybe Int, and Either String Int as well, none of these the same as Int. Since main is an IO function, it doesn't return Int, it returns IO Int. In fact, return is not a special construct in Haskell at all, it's just a normal function that happens to wrap a value in a Monad. In this case, the Monad being used is IO, so return (read inputjar :: Int) has the type IO Int.
To expand on #Zeta's comment below, Haskell's return is not special and more importantly does not exit functions early. The following code will demonstrate this:
doSomething :: IO Int
doSomething = do
return "Test" -- Wouldn't type-check if this exited early
return 123 -- Would type check, but is ignored
putStrLn "You'll see this line printed"
return () -- Doesn't affect anything
x <- getLine -- Still happens
return 5678
putStrLn "Your input is meaningless! Here's a 0"
return ([1, 2], "hello", "world")
return 0 -- This is the actual return value
All those extra returns do nothing in Haskell (at least in the IO monad). All that happens is a value is wrapped in a constructor and chained together with the rest of the statements in that function. There are even some people in the Haskell community that view return as both unnecessary and confusing. Technically, return is equivalent to pure for Applicatives, and all Monads are also Applicatives, so it's not really providing us anything. At some point in the distant future, it's possible that the return function might disappear entirely, being completely superseded by pure. Again, neither of these functions are part of Haskell syntax, they're defined in the core libraries as plain, normal functions.

Parsing user input with reads in Haskell

I am trying to parse user entered string like "A12", into a Haskell tuple, like ('A', 12).
Here's what I have tried:
import Data.Maybe
type Pos = (Char, Int)
parse :: String -> Maybe Pos
parse u = do
(c, rest) <- (listToMaybe.reads) u
(r, _) <- (listToMaybe.reads) rest
return $ (c, r)
But this always returns Nothing. Why does this happen, and what is the correct way to parse this string? Since this is fairly simple, I'd like to avoid using Parsec or a similar advanced parsing library.
EDIT (to clarify):
Sample Input and Output:
"A12" gives Just ('A', 12)
"J5" gives Just ('J', 5)
"A" gives Nothing
"2324" gives Nothing
read is usually the opposite of show and they both generally use Haskell syntax to represent the given values. This means that since the Haskell syntax for characters uses single quotes, show on a character will add single quotes around it, and read will expect the single quotes to be there.
In other words, your function expects syntax like 'A' 42, and indeed it works if you try that:
> parse "'A' 42"
Just ('A',42)
For your format, I would instead use pattern matching for the first character and then reads for the rest, e.g. something like this:
parse :: String -> Maybe Pos
parse [] = Nothing
parse (c:rest) = do
(r, _) <- listToMaybe $ reads rest
return (c, r)
Do you have to use do notation? If not, the following function suits your needs. It's not pretty, but it gets the job done.
parse :: String -> Maybe Pos
parse (x:xs) = Just (x,read xs::Int)
I'm not sure what you consider "failing" and thus worth of a Nothing

Resources