my task is to create menu with four choices: -add new students -show all students, -delete students by ID -close program. I used Hashmap for this problem, but the problem is that i have no idea how to display a current list of created students.
My code is presented below:
{module StudentApp where
import Data.HashMap.Strict
import System.Exit (exitSuccess)
data Student = Student {name::String, age::Int, id::String}
deriving (Show, Eq, Read)
type Students = HashMap String Student
addStudent:: Students -> IO(Students)
addStudent students = do
putStrLn ("Student Name")
name<-getLine
putStrLn("Student Age")
age<-readLn :: IO Int
putStrLn("Student ID")
id<-getLine
let s = Student name age id
let updatedStudents = insert id s students
return updatedStudents
showStudent:: Students -> IO (Students)
showStudent students = do
print students
return students
deleteStudent:: Students -> IO (Students)
deleteStudent students = do
putStrLn ("Give student ID to remove")
id<-getLine
let updatedStudents = delete id students
return updatedStudents
menu :: Students -> IO ()
menu students = do
putStrLn ("1. Add new student")
putStrLn ("2. Show all students")
putStrLn ("3. Delete Student by ID")
putStrLn ("4. Exit program")
choice<-getLine
updatedStudents <- case choice of
"1" -> addStudent students
"2" -> showStudent students
"3" -> deleteStudent students
"4" -> exitSuccess --System.Exit.exitSuccess (zwraca typ IO students)
menu updatedStudents
main :: IO ()
main = do
let students = empty :: Students
menu students
}
1 Answer 1
Given that the keys k
and the values v
are instances of Show
, then a HashMap
is an instance of Show
as well. Indeed in the source code, we see:
instance (Show k, Show v) => Show (HashMap k v) where showsPrec d m = showParen (d > 10) $ showString "fromList " . shows (toList m)
So we can use print :: Show a => a -> IO ()
here to print the content of the HashMap
. Like:
Prelude Data.HashMap.Strict> print (fromList [("id001", Student "Foo" 21 "id001"), ("id003", Student "Bar" 19 "id003")])
fromList [("id003",Student {name = "Bar", age = 19, id = "id003"}),("id001",Student {name = "Foo", age = 21, id = "id001"})]
So here print
contains as argument a HashMap String Student
we constructed, and this will print the content of the dictionary.
You can make use of ToList :: HashMap k v -> [(k, v)]
as well to convert your HashMap k v
into a list of key-value tuples, and then thus show the values with some extra functions.
For example we can print every value (here Student
) on a separate line with:
mapM_ (print . snd) (toList myhashmap)
In your menu you can thus write:
menu :: Students -> IO ()
menu students = do
putStrLn "1. Add new student"
putStrLn "2. Show all students"
putStrLn "3. Delete Student by ID"
putStrLn "4. Exit program"
choice <- getLine
updatedStudents <- case choice of
"1" -> addStudent students
--"2" -> showstudent
"3" -> deleteStudent students
"4" -> exitSuccess --System.Exit.exitSuccess (zwraca typ IO students)
print updatedStudents
menu updatedStudents
Advise: In your current program, you constantly use
do
blocks. Typically in a Haskell program, you write the logic that does not requireIO
, aState
, etc. separately in functions that do a small number of things.
13 Comments
menu updatedStudents
?do
block of your showStudent
be indented?