Jessie Richardson
Jessie Richardson

Reputation: 958

How to Pass a Function w/ an Argument to Another Function in Haskell?

I am making a simple Haskell todo list and I want to call a function "prompt" recursively and show different menu options based on user input. The problem is that upon initial call, prompt should expect to receive a function as one of the arguments that does NOT expect any arguments itself. Any following calls of "prompt" may need to call a function that DOES expect an argument passed to the function that is being passed to prompt.

Here is my code:

mainMenuOptions :: IO ()
mainMenuOptions = do
    putStrLn ""
    putStrLn "What would you like to do?"
    putStrLn ""
    putStrLn "OPTIONS"
    putStrLn ""
    putStrLn "'+' : add items    |   '-' : remove items"

subMenuOptions ::  [String] -> String -> IO ()
subMenuOptions todos operation = do
    putStrLn ""
    if operation == "add"
        then do putStrLn ("Type in the TASK you'd like to " ++ operation ++ ", then hit ENTER")
                addListItemOptions todos
    else do
        putStrLn ("Type in the NUMBER of the task you'd like to " ++ operation ++ ", then hit ENTER")
        putStrLn "('r' : return to the main menu)"

prompt :: [String] -> IO () -> IO ()
prompt todos showOptions = do
    showTasks todos
    showOptions
    input <- getLine
    interpret input todos


interpret :: String -> [String] -> IO ()
interpret input todos
    | input == "r" = prompt todos mainMenuOptions
    | input == "+" = prompt todos subMenuOptions "add"
    | input == "-" = prompt todos subMenuOptions "remove"
    | otherwise = do
                    putStrLn ""
                    putStrLn "SORRY, did not get that! Please enter a valid option."
                    prompt todos mainMenuOptions


main :: IO ()
main = do
    putStrLn "Haskell ToDo List"
    prompt [] mainMenuOptions

The error I get when I try to do this is:

Couldn't match expected type ‘[Char] -> IO ()’ with actual type ‘IO ()’ • The function ‘prompt’ is applied to three arguments, but its type ‘[String] -> IO () -> IO ()’ has only two

Upvotes: 4

Views: 1074

Answers (1)

luqui
luqui

Reputation: 60463

On this line

| input == "+" = prompt todos subMenuOptions "add"

First of all, prompt only takes 2 arguments, and we're passing it three, like the error said. For the second argument of prompt we want to pass it an IO () using subMenuOptions

subMenuOptions :: [String] -> String -> IO ()

which says that if we give it a list of strings and a string, it will give us the IO () we are looking for. So:

| input == "+" = prompt todos (subMenuOptions todos "add")

We need the parentheses because

prompt todos subMenuOptions todos "add"

would mean we are passing 4 arguments to prompt.

Upvotes: 5

Related Questions