Right now I have two types:
type Rating = (String, Int)
type Film = (String, String, Int, [Rating])
I have a file that has this data in it:
"Blade Runner"
"Ridley Scott"
1982
("Amy",5), ("Bill",8), ("Ian",7), ("Kevin",9), ("Emma",4), ("Sam",7), ("Megan",4)
"The Fly"
"David Cronenberg"
1986
("Megan",4), ("Fred",7), ("Chris",5), ("Ian",0), ("Amy",6)
How can I look through then file storing all of the entries into something like FilmDatabase = [Film] ?
Haskell provides a unique way of sketching out your approach. Begin with what you know
Attempting to load this program into ghci will produce
It needs to know what
readFilmsis, so add just enough code to keep moving.It is a function that should do something related to
Filmdata. Reload this code (with the:reloadcommand or:rfor short) to getfilms.hs:9:3: Ambiguous type variable `a0' in the constraint: (Show a0) arising from the use of `print' ...The type of
printisIn other words,
printtakes a single argument that, informally, knows how to show itself (that is, convert its contents to a string) and creates an I/O action that when executed outputs that string. It’s more-or-less how you expectprintto work:We know that we want to
printtheFilmdata from the file, but, although good, ghc can’t read our minds. But after adding a type hintwe get a new error.
films.hs:8:12: Couldn't match expected type `IO t0' with actual type `(String, String, Int, [Rating])' Expected type: IO t0 Actual type: Film In the return type of a call of `readFilms' In a stmt of a 'do' expression: films <- readFilms "ratings.dat"The error tells you that the compiler is confused about your story. You said
readFilmsshould give it back aFilm, but the way you called it inmain, the computer should have to first perform some I/O and then give backFilmdata.In Haskell, this is the difference between a pure string, say
"JamieB", and a side effect, say reading your input from the keyboard after prompting you to input your Stack Overflow username.So now we know we can sketch
readFilmsasand the code compiles! (But we can’t yet run it.)
To dig down another layer, pretend that the name of a single movie is the only data in
ratings.datand put placeholders everywhere else to keep the typechecker happy.This version compiles, and you can even run it by entering
mainat the ghci prompt.In dave4420’s answer are great hints about other functions to use. Think of the method above as putting together a jigsaw puzzle where the individual pieces are functions. For your program to be correct, all the types must fit together. You can make progress toward your final working program by taking little babysteps as above, and the typechecker will let you know if you have a mistake in your sketch.
Things to figure out:
String) to anIntto cooperate with your definition ofFilm?readFilmsaccumulate and return a list ofFilmdata?