Search code examples
haskellfunctoralgebraic-data-types

Haskell Error: Expected kind ‘* -> *’, but ‘Movie’ has kind ‘*’


I created a "Movie" algebraic data type (as requested by the task):

data Movie = Movie { title :: String, director :: String, releaseYear :: Int} 

Then added a functor:

instance Functor Movie where
    fmap _ Nothing = Nothing 
    fmap f (Movie title director releaseYear) = Movie (f title) (f director) (f releaseYear)

After that I wrote several functions to test the program's operation:

appendYear :: String -> String
appendYear title = title ++ " (2023)"

sampleMovie :: Movie
sampleMovie = Movie "Cool Film" "Amazing Director" 2000

modifiedMovie :: Movie
modifiedMovie = fmap appendYear sampleMovie

And after I try to call functions...

main :: IO ()
main = do
    print sampleMovie
    print modifiedMovie

...I have the following:

[1 of 1] Compiling Main             ( main.hs, main.o )
main.hs:3:18: error:
    • Expected kind ‘* -> *’, but ‘Movie’ has kind ‘*’
    • In the first argument of ‘Functor’, namely ‘Movie’
      In the instance declaration for ‘Functor Movie’
  |
3 | instance Functor Movie where
  |                  ^^^^^

Please help me figure out the problem. I have only recently started studying Haskell, so I use an online compiler

Tried to do something like this on other task:

data Possibly a = NotThere
                | There a 
                deriving (Show, Functor)
instance Functor Possibly where
    fmap _ NotThere = NotThere
    fmap f (There a) = There (f a)

...but it didn't lead me to anything.


Solution

  • There are a few problems here: first of all the:

    fmap _ Nothing = Nothing
    

    makes no sense: Nothing is a data constructor of the Maybe type, not of the Movie type.

    But the most important one is that the Functor works on a parameterized type: this allows to change the type. This thus means that the Movie should be defined like:

    data Movie a = Movie { title :: a, director :: String, releaseYear :: Int}
    
    instance Functor Movie where
        fmap f m(Movie {title=t}) = m { … }

    where I leave implementing the part as an exercise.