1

I have a hard-coded list that I wish to concatenate to a list-of-lists.

import Data.List (nub, sort)
import System.IO 

type Title = String
type Director = String
type Year = Int
type Mark = Int
type Rating = (String, Int)

-- Define Film type here
type Film = (Title, Director, Year, [Rating])

-- Define database type here
type Database = [Film]

main = do 
    addFilm
    print testDatabase

testDatabase :: [Film]
testDatabase = [("Casino Royale", "Martin Campbell",  2006, [("Garry",  8)])]

addFilm :: [Film] -> Film -> [Film]
addFilm a b = ("The BFG", "Steven Speilberg", 2016, []) : testDatabase

I get the error

Couldn't match expected type ‘IO a0’
            with actual type ‘[Film] -> Film -> [Film]’
Probable cause: ‘addFilm’ is applied to too few arguments
In a stmt of a 'do' block: addFilm
In the expression:
  do { addFilm;
       print testDatabase }

I feel I am missing something rather simple but for the life of me I can't see it.

My expected output is something like this

[("The BFG","Steven Speilberg",2016,[]),("Casino Royale","Martin Campbell",2006,[("Garry",8)])]
2
  • Are you sure that you get that error message for that code? The expression testDatabase : [("The BFG", "Steven Speilberg", 2016, [])] (which is indeed ill-typed) does not appear anywhere in the code you posted. Commented Mar 13, 2016 at 21:53
  • @sepp2k sorry I posted the wrong error message. I've made the edits. Commented Mar 13, 2016 at 21:56

3 Answers 3

4

You have two problems.

  1. Given the definition of addFilm, the type signature should just be addFilm :: [Film], since you aren't using the defined arguments nor are you actually passing any arguments when you do call it.

  2. Since you are using the function in the IO monad, you can't call it directly like this. The simplest fix is to simply use its return value as the argument to print:

    main = print addFilm
    

Another solution is to leave the type signature of addFilm as it is and actually use the arguments you pass it, then call it with appropriate arguments.

addFilm :: [Film] -> Film -> [Film]
addFilm a b = b : a
-- addFilm = (:)

main = do
          let newDatabase = addFilm testDatabase ("The BFG", "Steven Speilberg", 2016, [])
          print newDatabase
Sign up to request clarification or add additional context in comments.

Comments

2

addFilm requires two parameters

addFilm :: [Film] -> Film -> [Film]
addFilm a b = ....

yet you are calling it in main with none

main = do 
    addFilm

The compiler is telling you that you need two things here

main = do
    addFilm thing1 thing2

Comments

1

You've defined addFilm as a function that takes two arguments (even though you don't do anything with those arguments), but you then don't supply any arguments when you use it. That's what the error message is telling you.

But even if you do supply the arguments (or remove the arguments from the definition and change the type to [Film]), you still won't be able to use addFilm as a statement in main's do block. addFilm a b will produce a value of type [List], but statements in main's do block must have type IO a (for some a).

It looks like you may be under the impression that : is a side-effecting operation that's able to affect the value of testDatabase. It's not and nothing can ever be able to affect the value of testDatabase. Your current definition of addList is equivalent to this:

addList a b = [("The BFG", "Steven Speilberg", 2016, []), ("Casino Royale", "Martin Campbell",  2006, [("Garry",  8)])]

It's simply a list containing two movies. So using it as a statement makes no sense - it has no side-effects (if it did, it would have to have an IO type).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.