Haskell - Num vs Double, Int types [duplicate] - haskell

This question already has answers here:
`String' is applied to too many type arguments
(2 answers)
Closed 1 year ago.
Haskell noob here.
Im trying to make the following function and this error is extremely cryptic to me:
:{
myfunc::(Double a)=> a -> a -> a
myfunc a b = a + b
:}
and I get:
error:
• Expected kind ‘* -> Constraint’, but ‘Double’ has kind ‘*’
• In the type signature: myfunc :: (Double a) => a -> a -> a
The same goes for Int.
However, it I use Num type, I get no error:
:{
myfunc::(Num a)=> a -> a -> a
myfunc a b = a+b
:}
The same goes if I use just plain Int or Double without Double a
:{
myfunc::Double -> Double -> Double
myfunc a b = a+b
:}
My question:
How come is it, that I can use Num a, or just plan Double, Int, but I cannot use Double a, or Int a?
Regards.

First a terminology note: when GHC writes * here in the error messages, read it as Type, the kind of types†. It is for historical reasons that older versions of GHC write it with the asterisk symbol.
So, your error message is
• Expected kind ‘Type -> Constraint’, but ‘Double’ has kind ‘Type’
• In the type signature: myfunc :: (Double a) => a -> a -> a
Ok, ‘Double’ has kind ‘Type’ – that should make enough sense, right? Double is a type.
But why does it say it's “expecting” Type -> Constraint? Well, it means you tried to use Double as if it were of this kind. Namely, you wrote Double a. Here, a has to be a type, but you can't apply a type to another type, that would be like applying a character to a character on the value level:
Prelude> 'x' 'y'
<interactive>:1:1: error:
• Couldn't match expected type ‘Char -> t’ with actual type ‘Char’
• The function ‘'x'’ is applied to one argument,
but its type ‘Char’ has none
By contrast, Num is a type class, and as such it has in fact the correct kind:
Prelude> :k Num
Num :: Type -> Constraint
Constraint is the correct kind that's expected on the left of the =>, so that's why you can write
myfunc :: Num a => a -> a -> a
Again, Double is a type, not a type class, so it can't be used in this way. However, what you can use is an equality constraint:
{-# LANGUAGE TypeFamilies #-}
myfunc :: a~Double => a -> a -> a
myfunc = (+)
This is effectively the same as
myfunc :: Double -> Double -> Double
(there are some subtle differences with respect to typechecking).
Vice versa, it is not possible to write
myfunc :: Num -> Num -> Num
myfunc = (+)
error:
• Expecting one more argument to ‘Num’
Expected a type, but ‘Num’ has kind ‘Type -> Constraint’
• In the type signature: myfunc :: Num -> Num -> Num
†To be completely precise, Type is the kind of lifted types. Don't worry about what that means: unless you're doing very low-level stuff, you may never need to work with unlifted types.

Related

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

This question already has answers here:
`String' is applied to too many type arguments
(2 answers)
Closed 2 years ago.
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
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.)

What is a quick way to determine how many typed holes to give to a function?

Typed holes offer a great way of finding out how to implement something: if you know what function to use, say foo, you can just write out something like foo _ _ _ and let the compiler tell you what types it expects for each argument. This makes it largely unnecessary to look up any documentation.
However, it only works properly if you actually write out the correct number of underscores. At the moment, I usually determine this by some trial-and-error, but it's not always obvious what hints to look out for, because in Haskell functions can always be just partially applied.
What is a good way to find out this number as quickly as possible?
As #chi suggests, the best thing I've found is "apply the hole to the function". I don't know if this answers the question, but hopefully it is at least somewhat helpful.
I'm guessing that by "functions can always be just partially applied" you mean you can have such a function:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
foldr = undefined
for which you can't tell just from the type how many arguments it should take in order to typecheck at any particular type. The best that the typechecker can do here is to tell you the minimum number of arguments it will accept:
bar :: String -> String
bar = _1 foldr
* Found hole:
_1 :: ((a0 -> b0 -> b0) -> b0 -> t0 a0 -> b0) -> String -> String
Where: `t0' is an ambiguous type variable
`b0' is an ambiguous type variable
`a0' is an ambiguous type variable
* In the expression: _
In the expression: _ foldr
In an equation for `bar': bar = _ foldr
* Ambiguous type variable `t0' arising from a use of `foldr'
prevents the constraint `(Foldable t0)' from being solved.
Probable fix: use a type annotation to specify what `t0' should be.
These potential instances exist:
instance Foldable (Either a) -- Defined in `Data.Foldable'
instance Foldable Maybe -- Defined in `Data.Foldable'
instance Foldable ((,) a) -- Defined in `Data.Foldable'
...plus one other
...plus 22 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
Aside: the second error isn't particularly helpful here, as t0 could really be any of those types. But if you find yourself in such a situation often, then -fprint-potential-instances may actually be useful.
You can now do a little bit of typechecking in your head:
((a0 -> b0 -> b0) -> b0 -> t0 a0 -> b0 ) ->
<_1> <_2> String -> String
for the types to match, you must supply at least two holes. You may need more, but that will depend on the instantiation of b0. Substituting in these holes, you get a pretty easy problem
bar :: String -> String
bar = foldr _1 _2
* Found hole: _1 :: Char -> String -> String
* Found hole: _2 :: String
You may even encounter a (in my opinion, silly) function like
class C a where foo :: a
instance C String where
instance C a => C (Int -> a) where
in which case you can do the same thing, and the typechecker helpfully notifies you of all the possible instances:
bar :: String -> String
bar = _ foo
test0.hs:6:7: warning: [-Wtyped-holes]
* Found hole: _ :: t0 -> String -> String
Where: `t0' is an ambiguous type variable
* In the expression: _
In the expression: _ foo
In an equation for `bar': bar = _ foo
* Relevant bindings include
bar :: String -> String (bound at test0.hs:6:1)
test0.hs:6:9: warning: [-Wdeferred-type-errors]
* Ambiguous type variable `t0' arising from a use of `foo'
prevents the constraint `(C t0)' from being solved.
Probable fix: use a type annotation to specify what `t0' should be.
These potential instances exist:
instance C a => C (Int -> a) -- Defined at test0.hs:3:10
instance C String -- Defined at test0.hs:2:10
* In the first argument of `_', namely `foo'
In the expression: _ foo
In an equation for `bar': bar = _ foo
Here you really have to guess. In this (admittedly contrived) example, I would probably guess you want one argument, because bar takes one argument.
bar :: String -> String
bar = foo . _
test0.hs:6:7: warning: [-Wdeferred-type-errors]
* Ambiguous type variable `b0' arising from a use of `foo'
prevents the constraint `(C (b0 -> String))' from being solved.
(maybe you haven't applied a function to enough arguments?)
Probable fix: use a type annotation to specify what `b0' should be.
These potential instance exist:
instance C a => C (Int -> a) -- Defined at test0.hs:3:10
test0.hs:6:13: warning: [-Wtyped-holes]
* Found hole: _ :: String -> b0
Where: `b0' is an ambiguous type variable
Now it tells you there is one potential instance, and so you can guess that the type of that hole really should be String -> Int.

Haskell, multiple type classes for one argument

This is an example in Learn You A Haskell, chapter on higher order functions:
compareWithHundred :: (Num a, Ord a) => a -> Ordering
compareWithHundred x = compare 100 x
While the idea of the function is clear for me, I'm not sure why type signature is (Num a, Ord a). We only pass integer that is to be compared to the function, of type Int. What Ord stands for here, and why is implicitly passed argument in type signature?
That's not the only possible signature for this signature. It happens to be the most general one. compareWithHundred :: Int -> Ordering is actually a possible instantiation – the polymorphic a argument can be instatiated with any orderable number type, which does sure enough include Int, but also Integer, Rational, Double...
Prelude> let compareWithHundred :: (Num a, Ord a) => a -> Ordering; compareWithHundred x = compare 100 x
Prelude> compareWithHundred (99 :: Int)
GT
Prelude> compareWithHundred (100.3 :: Double)
LT
Not all number types permit you to order-compare them though – the classical example where this is not possible are complex numbers (which have “more than one direction” in which you could order them).
Prelude Data.Complex> compareWithHundred (100 :+ 30 :: Complex Double)
<interactive>:10:1:
No instance for (Ord (Complex Double))
arising from a use of ‘compareWithHundred’
In the expression: compareWithHundred (100 :+ 30 :: Complex Double)
In an equation for ‘it’:
it = compareWithHundred (100 :+ 30 :: Complex Double)
Hence you need to require both that the argument is a number (so there exists a value 100 which to compare with) and that the argument is in the Ord class. This combined constrained is written (Num a, Ord a).
I have something to add, in case you couldn't gather something from leftaroundabout's thorough answer.
Everything to the left of => in a type signature is a constraint. Read the type like this:
compareWithHundred :: (Num a, Ord a) => a -> Ordering
^^^^^^^^^^^^^^ ^ ^^^^^^^^
constraints | |
argument type |
result type
So you only pass one argument to the function because there is only one argument in the type signature, a. a is a type variable, and can be replaced with any type as long as that type satisfies the constraints.
The Num a says that whatever you replace a with has to be numeric (so it can be Int, Integer, Double, ...), and the Ord a says that it has to be comparable. leftroundabout's answer goes into more detail about why you need both, I just wanted to make sure you knew how to read the signature.
So it's perfectly legal in one sense to say compareWithHundred "foobar", the type checker says that that expression's type is Ordering, but then it will fail later when it tries to check that there is a Num String instance.
I hope this helps.

RankNTypes with type aliases confusion [duplicate]

This question already has answers here:
Understanding a rank 2 type alias with a class constraint
(2 answers)
Closed 6 years ago.
I'm trying to understand how type constraints work with type aliases. First, let's assume I have next type alias:
type NumList a = Num a => [a]
And I have next function:
addFirst :: a -> NumList a -> NumList
addFirst x (y:_) = x + y
This function fails with next error:
Type.hs:9:13: error:
• No instance for (Num a) arising from a pattern
Possible fix:
add (Num a) to the context of
the type signature for:
addFirst :: a -> NumList a -> a
• In the pattern: y : _
In an equation for ‘addFirst’: ad
Which is obvious. This problem already described here:
Understanding a rank 2 type alias with a class constraint
And I understand why we need {-# LANGUAGE RankNTypes #-} for such type aliases to work and why previous example doesn't work. But what I don't understand is why next example compiles fine (on ghc 8):
prepend :: a -> NumList a -> NumList a
prepend = (:)
Of course it fails in ghci if I try to pass wrong value:
λ: prepend 1 []
[1]
λ: prepend "xx" []
<interactive>:3:1: error:
• No instance for (Num [Char]) arising from a use of ‘prepend’
• When instantiating ‘it’, initially inferred to have
this overly-general type:
NumList [Char]
NB: This instantiation can be caused by the monomorphism restriction.
Seems like type type checking delayed at runtime :(
Moreover, some simple and seems to be the same piece of code doesn't compile:
first :: NumList a -> a
first = head
And produces next error:
Type.hs:12:9: error:
• No instance for (Num a)
Possible fix:
add (Num a) to the context of
the type signature for:
first :: NumList a -> a
• In the expression: head
In an equation for ‘first’: first = head
Can somebody explain what is going on here? I expect some consistency in whether function type checks or not.
Seems like type type checking delayed at runtime :(
Not really. Here it's may be a bit surprising because you get the type error in ghci after having loaded the file. However it can be explained: the file itself is perfectly fine but that does not mean that all the expressions you can build up using the functions defined in it will be well-typed.
Higher-rank polymorphism has nothing to do with it. (+) for instance is defined in the prelude but if you try to evaluate 2 + "argh" in ghci, you'll get a type-error too:
No instance for (Num [Char]) arising from a use of ‘+’
In the expression: 2 + "argh"
In an equation for ‘it’: it = 2 + "argh"
Now, let's see what the problem is with first: it claims that given a NumList a, it can produce an a, no questions asked. But we know how to build NumList a out of thin air! Indeed the Num a constraints means that 0 is an a and makes [0] a perfectly valid NumList a. Which means that if first were accepted then all the types would be inhabited:
first :: NumList a -> a
first = head
elt :: a
elt = first [0]
In particular Void would be too:
argh :: Void
argh = elt
Argh indeed!

Strange Haskell expression with type Num ([Char] -> t) => t

While doing some exercises in GHCi I typed and got the following>
ghci> (1 "one")
<interactive>:187:1:
No instance for (Num ([Char] -> a0)) arising from a use of ‘it’
In a stmt of an interactive GHCi command: print it
which is an error, howeve if I ask GHCi for the type of the expression it does not give any error:
ghci> :type (1 "one")
(1 "one") :: Num ([Char] -> t) => t
What is the meaning of (1 "one")?
Why does this expression gives an error, but GHCi tells it is well typed?
What is the meaning of Num ([Char] -> t) => t?
Thanks.
Haskell Report to the rescue! (Quoting section 6.4.1)
An integer literal represents the application of the function fromInteger to the appropriate value of type Integer.
fromInteger has type:
Prelude> :t fromInteger
fromInteger :: Num a => Integer -> a
So 1 is actually syntax sugar for fromInteger (1 :: Integer). Your expression, then, is:
fromInteger 1 "one"
Which could be written as:
(fromInteger 1) "one"
Now, fromInteger produces a number (that is, a value of a type which is an instance of Num, as its type tells us). In your expression, this number is applied to a [Char] (the string "one"). GHC correctly combines these two pieces of information to deduce that your expression has type:
Num ([Char] -> t) => t
That is, it would be the result (of unspecified type t) of applying a function which is also a Num to a [Char]. That is a valid type in principle. The only problem is that there is no instance of Num for [Char] -> t (that is, functions that take strings are not numbers, which is not surprising).
P.S.: As Sibi and Ørjan point out, in GHC 7.10 and later you will only see the error mentioned in the question if the FlexibleContexts GHC extension is enabled; otherwise the type checker will instead complain about having fixed types and type constructors in the class constraint (that is, Char, [] and (->)).
Haskell is a very flexible language, but also a very logical one in a rather literal sense. So often, things that in most languages would just be syntax errors, Haskell will look at them and try its darnedest to make sense of them, with results that are really confusing but are really just the logical consequence of the rules of the language.
For example, if we type your example into Python, it basically tells us "what you just typed in makes zero sense":
Python 2.7.6 (default, Sep 9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> (1 "one")
File "<stdin>", line 1
(1 "one")
^
SyntaxError: invalid syntax
Ruby does the same thing:
irb(main):001:0> (1 "one")
SyntaxError: (irb):1: syntax error, unexpected tSTRING_BEG, expecting ')'
(1 "one")
^
from /usr/bin/irb:12:in `<main>'
But Haskell doesn't give up that easily! It sees (1 "one"), and it reasons that:
Expressions of the form f x are function applications, where f has type like a -> b, x has type a and f x has type b.
So in the expression 1 "one", 1 must be a function that takes "one" (a [Char]) as its argument.
Then given Haskell's treatment of numeric literals, it translates the 1 into fromInteger 1 :: Num b => [Char] -> b. fromInteger is a method of the Num class, meaning that the user is allowed to supply their own implementations of it for any type—including [Char] -> b if you are so inclined.
So the error message means that Haskell, instead of telling you that what you typed is nonsense, tells you that you haven't taught it how to construct a number of type Num b => [Char] -> b, because that's the really strange thing that would need to be true for the expression to make sense.
TL;DR: It's a garbled nonsense type that isn't worth getting worried over.
Integer literals can represent values of any type that implements the Num typeclass. So 1 or any other integer literal can be used anywhere you need a number.
doubleVal :: Double
doubleVal = 1
intVal :: Int
intVal = 1
integerVal :: Integer
integerVal = 1
This enables us to flexibly use integral literals in any numeric context.
When you just use an integer literal without any type context, ghci doesn't know what type it is.
Prelude> :type 1
1 :: Num a => a
ghci is saying "that '1' is of some type I don't know, but I do know that whatever type it is, that type implements the Num typeclass".
Every occurrence of an integer literal in Haskell source is wrapped with an implicit fromInteger function. So (1 "one") is implicitly converted to ((fromInteger (1::Integer)) "one"), and the subexpression (fromInteger (1::Integer)) has an as-yet unknown type Num a => a, again meaning it's some unknown type, but we know it provides an instance of the Num typeclass.
We can also see that it is applied like a function to "one", so we know that its type must have the form [Char] -> a0 where a0 is yet another unknown type. So a and [Char] -> a0 must be the same. Substituting that back into the Num a => a type we figured out above, we know that 1 must have type Num ([Char] -> a0) => [Char] -> a0), and the expression (1 "one") has type Num ([Char] -> a0) => a0. Read that last type as "There is some type a0 which is the result of applying a [Char] argument to a function, and that function type is an instance of the Num class.
So the expression itself has a valid type Num ([Char] -> a0) => a0.
Haskell has something called the Monomorphism restriction. One aspect of this is that all type variables in expressions have to have a specific, known type before you can evaluate them. GHC uses type defaulting rules in certain situations when it can, to accomodate the monomorphism restriction. However, GHC doesn't know of any type a0 it can plug into the type expression above that has a Num instance defined. So it has no way to deal with it, and gives you the "No Instance for Num..." message.

Resources