0

我正在完成一个将高阶语言翻译成另一种语言的程序,但在处理我试图实现的接口时遇到了麻烦。

这个想法是它要求用户选择一个数字,然后检查它是否是一个数字,如果是,它后面跟着一行要求写出要翻译的给定术语。

如果数字是 4,它有一个额外的行要求替换术语,因此翻译函数需要 2 个 args 而不是 1。因此我希望有 3 行输入供用户完成,具体取决于前面回答,但是我的代码要求输入一个数字,然后打印下一个问题并直接返回到开头,再次打印第一行。

我注意到它不会测试从输入* (isDigit num) * 获取的 Char 的有效性,并且总是选择if(ord num /= 4)等于 True 的路径,即使我键入数字 4!

我已经尝试了几种方法来解决这个问题,但我迷路了。如果您知道任何更好的方法,我非常乐意完全更改我的界面代码,因为我想不出任何其他方法。

顺便说一句,我在 Haskell 上很业余。

main :: IO ()
main = do 
        putStrLn  "Choose a definition to be implemented:\n 1 - Def 1 dealing with a Generalised class of CRS terms without permutations,\n 2 - Def 2 which is an extension of Def 1 with permutations,\n 3 - Def 4 which takes a closed nominal term-in-context, returning a closed CRS (meta)term,\n 4 - Def 6 which extends on Def 4 by adding a ground nominal substitution to the arguments.\n Definition number: "
        num <- getChar
        unless (isDigit num)   (return ())
        def num       
        main

def :: Char -> IO String
def num = do
           putStrLn "write a nominal term-in-context: "
           hFlush stdout
           str <- getLine  
           case num of
               '1'   -> (return . readExp1) str
               '2'   -> (return . readExp2) str
               '3'   -> (return . readExp4) str
               '4'   -> do
                         putStrLn "write a nominal term and the variable it substitutes:"              
                         sub <- getLine
                         let term = readExp6 str (readSub sub)
                         return term

{- reads and ouputs type TrmCxt ((atm,Var),Trm)         -}  
readExp1 :: String -> String
readExp1 s = case (inputL parseT s) of
           Left err -> "error: " ++ err
           Right (fc , t) -> show $ translate1 [] fc  t

我在代码片段中添加了函数readExp1,它解析输入并调用翻译函数,以便您了解它的作用和返回的内容。其他的返回类型是等价的。

4

3 回答 3

1

ord num /= 4是不正确的。一个最小的修复是num /= '4'改用。

更好的方法是为'4' ->.

您应该def按照@Yitz 的建议打印结果。您看到的错误是因为def num :: IO String. 您不能直接将其传递给 putStrLn。所以你应该使用

def num >>= putStrLn

或者

df <- def num
putStrLn df

在 do-block 中main

于 2013-09-30T16:18:05.913 回答
0

unless (isDigit num) (return ())什么也没做。

从文档中:“除非:与何时相反。” 如果布尔值 debug 为 True,则"when debug (putStr "Debugging\n")将输出字符串 Debugging\n,否则不执行任何操作。"

如果isDigit num是 False,我们执行动作return ();否则,我们“什么都不做”,这被定义为 action return ()

替换以下

unless (isDigit num)   (return ())
def num       
main

when (isDigit num) $ do
    def num       
    main

将调用def num然后继续你的循环 if isDigit num,否则它将立即退出(我不确定这是否是你想要发生的)。

于 2013-10-01T22:21:48.830 回答
0

def num您的语句中的行do不会产生任何输出。它只是翻译术语,丢弃结果String,然后继续重复main

你可能想要类似的东西

ans <- def num

    putStrLn ans

反而。

另请参阅@nponeccop 在不同答案中指出的另一个错误。

于 2013-09-30T16:34:48.793 回答