提问人:skiboy108 提问时间:12/13/2022 更新时间:12/14/2022 访问量:122
使用表达式树解析输入
Parsing Input Using Expression Tree
问:
因此,我尝试获取用户输入,然后将其解析为我为其设置了表达式树的表达式。我拥有的表达式树是:
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赞
gltronred
12/13/2022
#1
如果你在 do-notation 中使用了一些东西,它就在 Monad 中(或者 Applicative,如果你打开一些语言编译指示)。
所以,你的代码
expression <- getLine
read expression
写在单子里。然后应该有一个类型,用于一些单子和一些类型。编译器可以从 的类型推断出 ,所以是 。read expression
m a
m
a
m
getLine :: IO String
m
IO
但有类型.因此,应该是 .但是没有 for 的实例,您不能将字符串转换为返回某些内容的 IO 操作。read
read :: Read b => String -> b
b
IO a
Read
IO a
问题是你想执行纯计算。为此,您必须使用:let
expression <- getLine
let parsed = read expression :: Expression
print parsed
在这里,我用于将名称绑定到 的结果。然后你必须做一些 值 ,例如,你可以打印它。let
parsed
read expression
parsed
我必须指定类型,因为可以处理任何具有实例的东西,而编译器无法选择 .如果我写一些更具体的东西,比如 ,那么可以省略类型声明。print
Show
parsed
performOperation :: Expression -> IO ()
评论
0赞
skiboy108
12/14/2022
这奏效了,谢谢!除此之外,我唯一需要做的就是定义我希望它被解析为的类型。所以:
0赞
skiboy108
12/14/2022
let parsed = read expression :: 表达式
1赞
Daniel Wagner
12/14/2022
我宁愿,鉴于我们已经进入了,作为一个小习惯。 当事情出错时,在更好的时间抛出更好的异常。parsed <- readIO expression
IO
readIO
0赞
gltronred
12/14/2022
@skiboy108是的,我忘了。您必须添加类型,因为可以处理任何具有实例的内容,因此编译器在类型推理方面需要帮助。如果你做一些特定的事情而不是(比如),那么你可以省略类型print
Show
print
performOperation :: Expression -> IO ()
评论