Haskell:案例陈述问题

时间:2018-04-17 17:29:27

标签: haskell functional-programming logic case

我是Haskell的新手,我必须为大学做一个项目。我在使用案例陈述时遇到了麻烦。

case words command of
        ("Highlight":_) -> putStrLn ("Highlight                   |              \x1b[32m\x1b[107m" ++ show (aLine) ++ "\x1b[0m")
        ("InsertChar":_) -> putStrLn ("Insert Char                 |              " ++ show (insertChar aLine))
        ("DelCharRight":_) -> putStrLn ("Delete Char Right           |              " ++ show (delCharRight aLine))
        ("DelCharLeft":_) -> putStrLn ("Delete Char Left            |              " ++ show (delCharLeft aLine)) 
        ("CharRight":_) -> putStrLn ("Move Char Right             |              " ++ show (charRight aLine))
        ("CharLeft":_) -> putStrLn ("Move Char Left              |              " ++ show (charLeft aLine))
        ("WordRight":_) -> putStrLn ("Move Word Right             |              " ++ show (wordRight aLine))
        ("WordLeft":_) -> putStrLn ("Move Word Left              |              " ++ show (wordLeft aLine))
        ("EndLineRight":_) -> putStrLn ("End Line Right              |              " ++ show (endLineRight aLine))
        ("EndLineLeft":_) -> putStrLn ("End Line Left               |              " ++ show (endLineLeft aLine))
        ("HighlightRight":_) -> putStrLn ("Highlight Right             |              " ++ show (highlightRight aLine))
        ("HighlightLeft":_) -> putStrLn ("Highlight Left              |              " ++ show (highlightLeft aLine))
        ("HighlightWordRight":_) -> putStrLn ("Highlight Word Right        |              " ++ show (highlightWordRight aLine))
        ("HighlightWordLeft":_) -> putStrLn ("Highlight Word Left         |              " ++ show (highlightWordLeft aLine))
        ("Copy":_) -> putStrLn ("Copy                        |              " ++ show (copy aLine))
        ("Cut":_) -> putStrLn ("Cut                         |              " ++ show (cut aLine))
        ("Paste":_) -> putStrLn ("Paste                       |              " ++ show (paste aLine))
        ("Destroy":_) -> putStrLn ("Destroy                     |              " ++ show (destroy aLine))
        ("ClearScreen":_) -> clearScreen
        ("Save":_) -> writeFile savePath (command ++ "           |              " ++ show (save aLine))
        _ -> putStrLn "Error: Incorrect Command"
    return command

如何在同一行命令中添加更多代码?我想要这样的东西:

("DelCharRight":_) -> putStrLn ("Delete Char Right           |              " ++ show (delCharRight aLine) let bLine = delCharRight aLine let aLine = bLine

这基本上允许我在每个命令后覆盖一行,这样我就可以继续输入命令来编辑文本行。

麻烦是案例陈述不允许我使用'让'。

我为可怕的代码和解释道歉!

2 个答案:

答案 0 :(得分:1)

要回答您的确切问题,您只需在do

之后添加->即可
("DelCharRight":_) -> do
    putStrLn ("Delete Char Right           |              " ++ show (delCharRight aLine) 
    let bLine = delCharRight aLine 
    let aLine = bLine

但它没有帮助--Haskell中的let声明无法做到你想要的。作为一般规则,您不能在Haskell中改变数据。 aLine只会有一个值。如果您有命令式编程的背景知识,您可能会查看以下代码并(错误地)推断出某种突变正在发生,x会改变它的值。但所有这些都是阴影(尝试let x = x + x),看看它是做什么的。

someFunc :: IO ()
someFunc = do
    let x = 3
    let x = 5
    print x

那就是说,因为你在IO,你可以获得突变。 IORefs(在Data.IORef中找到)是可以使用的可变引用。

someFunc' :: IO ()
someFunc' = do
    x <- newIORef 3
    writeIORef x 5
    readIORef x >>= print

但我建议不要使用IORef。写一个单独的函数来返回更改后的值,然后将结果作为输入提供给下一个调用,这是更惯用的Haskell。这是一个简单&#34;计数器&#34;。

的技术示例
main :: IO ()
main = do
    commandLine <- getLine
    let commands = words commandLine
    counter <- runCounter commands 0
    print counter

-- There is a higher-order functions (foldM) that we 
-- could use instead of this function
-- but we'll avoid it for the sake of clarity
runCounter :: [String] -> Int -> IO Int
runCounter [] counter = return counter
runCounter (cmd:cmds) counter = do
    newCounter <- updateCounter cmd counter
    runCounter cmds counter

updateCounter :: String -> Int -> IO Int
updateCounter command counter = case command of
    "UP" -> do
        putStrLn "Incrementing counter"
        return (counter + 1)
    "DOWN" -> do
        putStrLn "Decrementing counter"
        return (counter - 1)

答案 1 :(得分:0)

选项1:添加do

case ... of
  ...
  ("DelCharRight":_) -> do
     let bLine = delCharRight aLine
         aLine = bLine
     putStrLn (...)

选项2:使用let .. in ..

case ... of
  ...
  ("DelCharRight":_) ->
     let bLine = delCharRight aLine
         aLine = bLine
     in putStrLn (...)

选项2更为通用,因为即使我们不在某个monad中工作(我们在IO内部也是如此,所以do也是可能的)。