Reputation: 59
So I am trying to take a user input and then parse it into an expression that I have set up an expression tree for. The expression tree that I have is:
data Expression = State [Float] Float
| Const Float
| Plus Expression Expression
| Times Expression Expression
| Minus Expression Expression
| Divide Expression Expression
| Uminus Expression
deriving(Show, Read)
And then I am trying to take the input and then parse it using the following two lines.
expression <- getLine
read expression
Is there something that I am missing regarding either getting the input or in my use of read? The error that it is giving me is:
Main.hs:94:3: error:
• No instance for (Read (IO a0)) arising from a use of ‘read’
• In a stmt of a 'do' block: read expression
In the expression:
do putStrLn "Input an expression to evaluate"
expression <- getLine
read expression
print ("Hello World")
....
In an equation for ‘main’:
main
= do putStrLn "Input an expression to evaluate"
expression <- getLine
read expression
....
Upvotes: 0
Views: 159
Reputation: 256
If you use something inside a do-notation, it is in the Monad (or Applicative, if you turn on some language pragmas).
So, your code
expression <- getLine
read expression
is written inside a monad. Then read expression
is expected to have a type m a
for some monad m
and some type a
. Compiler can infer m
from the type of getLine :: IO String
, so m
is IO
.
But read
has type read :: Read b => String -> b
. Therefore, b
should be IO a
. But there is no instance of Read
for IO a
, you can't convert a string into an IO action returning something.
The problem is that you want to perform pure computation. To do so you have to use let
:
expression <- getLine
let parsed = read expression :: Expression
print parsed
Here I use let
to bind a name parsed
to the result of read expression
. Then you have to do something with a value parsed
, for example, you can print it.
I have to specify the type because print
can work with anything that has Show
instance, and the compiler can't select the specific type of parsed
. If I write something more specific, like performOperation :: Expression -> IO ()
, then the type declaration can be omitted.
Upvotes: 1