Search code examples
haskellalgebraic-data-types

Error: No instance for (Num Price) arising from the literal


I'm praticing Haskell and I'm trying to create e movies store.

I created the types Code,Name,Genre and Price, a tuple Movie and a tuple list Movies and when I try add movies at tableMovies appear the message:

Prelude> :l movies
[1 of 1] Compiling Main             ( movies.hs, interpreted )

movies.hs:11:45:
    No instance for (Num Price) arising from the literal `50'
    Possible fix: add an instance declaration for (Num Price)
    In the expression: 50
    In the expression: (1, "Movie 1", "Adventure", 50)
    In the expression:
      [(1, "Movie 1", "Adventure", 50), (2, "Movie 2", "Horror", 30)]
Failed, modules loaded: none.
Prelude>

My code:

type Code = Integer
type Name = String
type Genre = String
data Price = Integer | Float

type Movie = (Code, Name, Genre,Price)

type Movies = [(Movie)]

tableMovies :: Movies
tableMovies = [ (001,"Movie 1", "Adventure",50)
             , (002,"Movie 2", "Horror", 30)]

I found some answers for this problem but I couldn't understand because the codes were very complexity to me. I'm only starting on Haskell


Solution

  • data Price = Integer | Float
    

    This line creates three things: The type Price, and the constants Integer and Float. It works exactly like:

    data Bool = False | True
    

    In your case you have the new values Integer (of type Price) and Float (of type Price). These are unrelated to the types Integer and Float. And 50 is not a value of type Price (Price has only two possible values).

    The whole thing is a bit confusing because types and values live in different namespaces. You can have a type called X and a value called X and they have nothing to do with each other (or in your case, a type called Integer and a value called Integer).

    To create a type that contains either an integer or a float, you can do this:

    data Price = PriceInteger Integer | PriceFloat Float
    

    Now you can do PriceInteger 50 and it will have type Price (but you still can't use a bare 50). It's probably easier to just do type Price = Integer and not allow floats.