haskell 使用表达式树解析输入

2eafrhcq  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(169)

因此,我尝试获取用户输入,然后将其解析为一个表达式,并为该表达式设置表达式树。

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
                 ....
xdnvmnnf

xdnvmnnf1#

如果你在do标记法中使用了什么,那么它就是在Monad(或者是Appliative,如果你打开了一些语言的pragma)中。
所以你的密码

expression <- getLine
read expression

写在一个单子里面。那么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

expression <- getLine
let parsed = read expression :: Expression
print parsed

这里我使用let将一个名称parsed绑定到read expression的结果,然后你必须对一个值parsed做一些事情,例如,你可以打印它。
我必须指定类型,因为print可以处理任何具有Show示例的对象,而编译器无法选择parsed的特定类型。如果我编写更具体的对象,如performOperation :: Expression -> IO (),则可以省略类型声明。

相关问题