0 Replies - 922 Views - Last Post: 06 November 2016 - 01:34 PM

#1 NoYouDidnt  Icon User is offline

  • D.I.C Head

Reputation: 5
  • View blog
  • Posts: 55
  • Joined: 04-July 15

Need help with haskell io program

Posted 06 November 2016 - 01:34 PM

Hello. Im doing some homework. Making a program that let a user do stuff with a "database".

I lack experience with Haskell and my code is really big. Right now my menu system looks like this

type Choice = (String, String, IO ())

choices :: [Choice]
choices = 
    [("a", "create a database", createdb),
    ("b", "delete a database", deletedb),
    ("c", "insert an entry to a database", insert),
    ("d", "print a database", selectall),
    ("e", "select entries from a database", select),
    ("f", "delete entries from a database", delete),
    ("g", "update entries from a database", update),
    ("q", "quit", quit)]

menu :: IO ()
menu = do
    (mapM_ putStrLn . map showChoice) choices
    c <- get "Enter the letter corresonding to the action of choice:"
    case filter ((== c) . fst3) choices of
        [] -> back "Not a valid choice. Try again"
        (_, _, f) : _ -> f

For most of the choices im working with manipulating a text file.
Here is a couple of the functions and some helper functions i made to desperately make the code shorter

createdb :: IO ()
createdb = do
    n <- maybeName
    if isNothing n then menu else do
        let name = fromJust n
        fp <- maybeFile name
        if isJust fp
        then back $ "Error: \"" ++ name ++ "\" already exist." 
        else do
            cols <- get "Enter unique column names in the form n1,n2,...,n (No spaces):"
            let spl = (splitOnComma . toLower') cols
            case filter (== True) (hasDuplicates spl : map (elem ' ') spl) of
                [] -> writeFile (name ++ ".txt") (cols ++ "\n")
                _  -> back "Error: Column names must be unique and have no spaces."
deletedb :: IO ()
deletedb = do
    n <- maybeName
    if isNothing n then menu else do
        let name = fromJust n
        fp <- maybeFile name
        if isJust fp
        then removeFile (fromJust fp) 
        else back $ "Error: Could not find " ++ name

maybeName :: IO (Maybe String)
maybeName = do
    input <- get "Enter database name or 'b' to go back to the menu."
    return $ case input of
        "b" -> Nothing
        _   -> Just input 
maybeFile :: String -> IO (Maybe FilePath)
maybeFile name = do
    let fn = name ++ ".txt"
    exists <- doesFileExist fn
    return $ if exists then Just fn else Nothing

back :: String -> IO ()
back msg = do
    putStrLn msg
get :: String -> IO String
get msg = do
    putStrLn msg

As you can see I am asking for the filename etc every time. And I am doing this for all the functions in the menu (except quit). I would really like to separate this. Wonder if someone can give me some advice

This post has been edited by NoYouDidnt: 06 November 2016 - 01:40 PM

Is This A Good Question/Topic? 0
  • +

Page 1 of 1