Reputation: 13
I'm new to Haskell and i have to do a project for university. I'm having trouble using a case statement.
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
How would i add more code to the same line of command? I want something like this:
("DelCharRight":_) -> putStrLn ("Delete Char Right | " ++ show (delCharRight aLine) let bLine = delCharRight aLine let aLine = bLine
This basically allows me to overwrite a Line after each command so i can keep typing the commands to edit the line of text.
Trouble is the case statement won't let me use 'Let'.
I apologise for the terrible code and explanation!
Upvotes: 1
Views: 130
Reputation: 1361
To answer your exact question, you can just add do
after the ->
("DelCharRight":_) -> do
putStrLn ("Delete Char Right | " ++ show (delCharRight aLine)
let bLine = delCharRight aLine
let aLine = bLine
But it won't help - a let
statement in Haskell can't do what you want. As a general rule, you can't mutate data in Haskell. aLine
will only ever have one value. If you have a background in imperative programming, you might look at the following code and (incorrectly) deduce that some sort of mutation is going on, with x
changing it's value. But all that's going on is shadowing (try let x = x + x
) and see what that does.
someFunc :: IO ()
someFunc = do
let x = 3
let x = 5
print x
That said, because you are in IO
you do have access to mutation. IORefs (found in Data.IORef) are mutable references that you could make use of.
someFunc' :: IO ()
someFunc' = do
x <- newIORef 3
writeIORef x 5
readIORef x >>= print
But I'd recommend against using an IORef
. It's much more idiomatic Haskell to write a separate function which returns the changed value, and then feed the result back in as an input on the next call. Here's an example of that technique for a simple "Counter".
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)
Upvotes: 1
Reputation: 116139
Option 1: add a do
case ... of
...
("DelCharRight":_) -> do
let bLine = delCharRight aLine
aLine = bLine
putStrLn (...)
Option 2: use let .. in ..
case ... of
...
("DelCharRight":_) ->
let bLine = delCharRight aLine
aLine = bLine
in putStrLn (...)
Option 2 is more general, since it works even when we are not working inside some monad (here we are inside IO
, so do
is also a possibility).
Upvotes: 0