Syntax in Functions (Expected kind `* -> Constraint', but `Int' has kind `*')

Viewed 3354

I'm starting to learn Haskell and I'm struggling with syntax in Functions. I'm trying to create a function that receives a Number 'e' and a Number 'n', returning a list with of 'n' times 'e'.

Example: repn 3 5 would return [3,3,3,3,3]:

repn :: Int a => a -> a -> [a]
repn e n
    | n >= 1 = (take n (repeat e))
    | otherwise = []

But I'm getting this error:

* Expected kind `* -> Constraint', but `Int' has kind `*'
    * In the type signature: replica :: Int a => a -> a
2 Answers

As a rule of thumb, writing something of the form Foo a => ... only makes sense of Foo is a type class. Unlike in OO languages, a class and a type in Haskell are completely different things. Int is a type, therefore it cannot be used in this way; instead you should simply use

repn :: Int -> Int -> [Int]

...though actually there's no reason to restrict the list-element type at all, the signature could as well be

repn :: a -> Int -> [a]

Alternatively, you can use a type class: the class of “int-like types” is Integral. Then you can't use take directly, as that is restricted to Int for the counter argument; however you can convert any integral type to Int:

repn :: Integral n => a -> n -> [a]
repn e n = take (fromIntegral n) $ repeat e
    -- Note no case distinction is needed, because `take` already yields
    -- an empty list if `n<1`.

Your type definition is not correct. The double arrow is used to show required typeclasses (aka kind * -> Constraint), or a constraint on types. However, Int is itself a type (aka kind *).

You can't specify types in this way. In your implementation, n must be an Int, but e could be anything. Since you specify that it should be a number, though, you can constrain it with the Num typeclass. The correct version of your signature therefore is:

repn :: Num a => a -> Int -> [a]

If you want e to be constrained to an Int, then your signature should be

repn :: Int -> Int -> [Int]

If you don't need any constraints on e, your signature can be

repn :: a -> Int -> [a]

These are all valid type signatures for the function you have written. (Though in actual code, I would just point you to the builtin replicate function.)

Related