因此,我尝试获取用户输入,然后将其解析为一个表达式,并为该表达式设置表达式树。
data Expression = State [Float] Float
| Const Float
| Plus Expression Expression
| Times Expression Expression
| Minus Expression Expression
| Divide Expression Expression
| Uminus Expression
deriving(Show, Read)
然后我尝试获取输入,然后使用下面两行代码解析它。
expression <- getLine
read expression
在获取输入或使用read时是否遗漏了什么?它给我的错误是:
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
....
1条答案
按热度按时间xdnvmnnf1#
如果你在do标记法中使用了什么,那么它就是在Monad(或者是Appliative,如果你打开了一些语言的pragma)中。
所以你的密码
写在一个单子里面。那么
read expression
对于一些单子m
和一些单子a
应该有一个类型m a
。编译器可以从getLine :: IO String
的类型推断m
,所以m
就是IO
。但是
read
的类型是read :: Read b => String -> b
,所以b
应该是IO a
,但是IO a
没有Read
的示例,你不能把一个字符串转换成一个IO操作返回一些东西。问题是你想执行纯计算,为此你必须使用
let
:这里我使用
let
将一个名称parsed
绑定到read expression
的结果,然后你必须对一个值parsed
做一些事情,例如,你可以打印它。我必须指定类型,因为
print
可以处理任何具有Show
示例的对象,而编译器无法选择parsed
的特定类型。如果我编写更具体的对象,如performOperation :: Expression -> IO ()
,则可以省略类型声明。