Skip to content

Instantly share code, notes, and snippets.

@osa1
Created February 18, 2012 18:21
Show Gist options
  • Save osa1/1860526 to your computer and use it in GitHub Desktop.
Save osa1/1860526 to your computer and use it in GitHub Desktop.
I wrote 103 lines of imperative code in Haskell :P
module Main where
{-
I wrote this to get a bettern understanding of Haskell way of doing
side effects, which turns out, is not much fun :)
-}
import Todo
import System.Environment
import System.FilePath
import System.IO
import Data.List
import Data.Time
{-
Beware! Most complex syntax since C++ ahead !
-}
main = do
handle <- openFile "todos.txt" ReadMode
todos <- readTodos handle []
hClose handle
app todos
menu = [ ("Add Todo", addTodo)
, ("Remove Todo", removeTodo)
, ("Save", writeTodos)
]
app :: [Todo] -> IO ()
app todos = do
showTodos todos
showMenu
input <- getLine
let selection = read input :: Int
newTodos <- snd (menu !! selection) todos
app newTodos
showTodos todos = do
let todoStrs = map show todos
mapM_ (\todo -> putStr $ todo ++
concat (take 50 (repeat "-")) ++ "\n") todoStrs
today :: IO Day
today = do
t <- getZonedTime
return (localDay $ zonedTimeToLocalTime t)
hGetNonEmptyLine :: Handle -> IO String
hGetNonEmptyLine handle = do
line <- hGetLine handle
if line == ""
then hGetNonEmptyLine handle
else return (line)
readTodo :: Handle -> IO Todo
readTodo handle = do
desc <- hGetNonEmptyLine handle
priorityS <- hGetNonEmptyLine handle
deadlineS <- hGetNonEmptyLine handle
let priority = read priorityS :: Int
let deadline = read deadlineS :: Day
return (Todo desc priority deadline)
readTodos :: Handle -> [Todo] -> IO [Todo]
readTodos handle todos = do
eofp <- hIsEOF handle
if eofp
then return todos
else do nextTodo <- readTodo handle
readTodos handle (insert nextTodo todos)
writeTodos :: [Todo] -> IO [Todo]
writeTodos todos = do
handle <- openFile "todos.txt" WriteMode
mapM_ (\todo -> let str = desc todo ++ "\n" ++ show (priority todo)
++ "\n" ++ show (deadline todo)
in hPutStrLn handle str) todos
hClose handle
return todos
removeTodo :: [Todo] -> IO [Todo]
removeTodo todos = do
idx <- readId
return $ removeIdx idx todos
addTodo :: [Todo] -> IO [Todo]
addTodo todos = do
putStr "Todo description: "
descS <- getLine
putStr "Todo priority: "
priS <- getLine
let priority = read priS :: Int
putStr "Todo deadline(YYYY-MM-DD): "
dayS <- getLine
let day = read dayS :: Day
return $ insert (Todo descS priority day) todos
removeIdx n lst = (take n lst) ++ (drop (n+1) lst)
readId :: IO Int
readId = do
putStr "Enter index of Todo item: "
input <- getLine
let id = read input :: Int
return id
showMenu = do
mapM_ (\menuItem -> do putStrLn $ "[" ++ (show $ fst menuItem) ++ "] "
++ (fst $ snd menuItem)) (zip [0..] menu)
putStr "> "
module Todo where
import Data.Time
import Data.List
data Todo = Todo { desc :: String
, priority :: Int
, deadline :: Day }
instance Show Todo where
show (Todo desc pri dl) = "Description: " ++ desc ++ "\nPriority: " ++ show pri
++ "\nDeadline: " ++ show dl ++ "\n"
instance Eq Todo where
Todo _ _ p1 == Todo _ _ p2 = p1 == p2
instance Ord Todo where
compare (Todo _ _ p1) (Todo _ _ p2) = compare p2 p1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment