''Type' has kind '*' - Haskell [closed]

In my code which is a rather simple case function whereby if a 'tool' is 'nothing' then go to the next tool, so on, so forth. :

nextTool :: Tool -> Tool
  nextTool l = 
      case l == nothing of
        LineTool nothing -> PolygonTool nothing
        PolygonTool [] -> CircleTool nothing
        CircleTool nothing -> TriangleTool nothing
        TriangleTool nothing -> RectangleTool 1.0 nothing
        RectangleTool 1.0 nothing -> CapTool nothing
        CapTool nothing -> LineTool nothing
        _ -> nextTool

But I have this error which states:

• Expected kind ‘k0 -> k1 -> *’, but ‘Tool’ has kind ‘*’

• In an expression type signature: Tool -> Tool nextTool l
  In the expression:
      otherwise == "Error" nextTool :: Tool -> Tool nextTool l
  In a stmt of a pattern guard for
                 an equation for ‘nextColour’:
      otherwise == "Error" nextTool :: Tool -> Tool nextTool l

Here, Tool is defined as:

data Tool 
  = LineTool (Maybe Point) 
  | PolygonTool [Point] 
  | CircleTool (Maybe Point) 
  | TriangleTool (Maybe Point) 
  | RectangleTool Double (Maybe Point) 
  | CapTool (Maybe Point) (Maybe Point) 
  deriving (Eq, Show) 

I am clueless as to what this means. Could someone tell me what it means and the required fix for it please?



Solution 1:[1]

Because you indented the nextTool l = ..., your code is parsed as

(nextTool :: Tool -> (Tool
  nextTool l)) = 
      case l == nothing of ...

or, with different alignment

(nextTool :: Tool -> (Tool nextTool l))
  = case l == nothing of ...

That doesn't make any sense of course, but surprisingly enough this style is in principle a valid way of defining a function. (See explanation below.)

What you tried to write instead was

nextTool :: Tool -> Tool
nextTool l = ...

You seem to have another indentation error in the preceding function in your file, which is why otherwise == "Error" appears in the error message.

Both otherwise == "Error" and your case construct with l == nothing don't make any sense either. You normally have otherwise in guards, but then it needs to be | otherwise = "Error" (notice the single =). And nothing is a variable name at this point that's probably not even defined; even if it were defined (or if you meant Nothing, which would however have the wrong type), the result of l == nothing would be a boolean, i.e. not something you can match on those tool-constructors.

I think what you wanted to write was simply

nextTool :: Tool -> Tool
nextTool (LineTool n) = PolygonTool n
nextTool (PolygonTool []) = CircleTool Nothing
nextTool (CircleTool n) = TriangleTool n
nextTool (TriangleTool n) = RectangleTool 1.0 n
nextTool (RectangleTool _ n) = CapTool n
nextTool (CapTool n) = LineTool n

This is probably still wrong, but can't be answered better since you didn't provide the definition of your Tool type.


So, why did your original code not just give some parse error or something else that made it clear that the indentation was wrong? What was that about kinds?

Well, because nextTool and l appear as lowercase identifiers in the signature, the compiler treats them as implicitly quantified type variables, and you're defining simply a constant called nextTool which is supposed to have the (nonsensical) type Tool -> Tool nextTool l. That type is what caused the error GHC gave you: in order to have Tool nextTool l (regardless of what nextTool and l are), Tool needs to have a kind of the form k -> l -> m. An example of a type that matches this would be the standard

data Either a b = Left a | Right b

Here we have

ghci> :k Either
Either :: Type -> Type -> Type

(in older GHC it is * -> * -> *, which means the same). This kind means that the Either type constructor should be applied to two types, in order to give you the complete variant type.

foo :: Either Int Double -> Double
foo (Left i) = fromIntegral i
foo (Right n) = negate n

But Tool is not of this form, it is simple

ghci> :k Tool
Tool :: Type

i.e. you can't apply it to any arguments, whether concrete ones like in foo above or implicitly quantified ones like nextTool and l in your code.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1