Reputation: 27180
I was so sleepy that I wrote the following code (modified to just show the confusion):
fac s = take 10 [s, s `mod` 1 ..]
maxFactor x = if (s == [])
then x
else head <-- this should be 'head x' instead of just 'head'
where s = fac x
However, this load into ghci (and compiles) just fine. When I executed maxFactor 1
, it complains (of course):
<interactive>:0:1:
No instance for (Integral ([a0] -> a0))
arising from a use of `maxFactor'
Possible fix:
add an instance declaration for (Integral ([a0] -> a0))
In the expression: maxFactor 1
In an equation for `it': it = maxFactor 1
<interactive>:0:11:
No instance for (Num ([a0] -> a0))
arising from the literal `1'
Possible fix: add an instance declaration for (Num ([a0] -> a0))
In the first argument of `maxFactor', namely `1'
In the expression: maxFactor 1
In an equation for `it': it = maxFactor 1
However, I don't understand this behavior:
fac
's type is:
fac :: Integral a => a -> [a]
while maxFactor
's type is:
maxFactor :: Integral ([a] -> a) => ([a] -> a) -> [a] -> a
Doesn't this mean the following:
fac
must be of typeclass Integral
(e.g., fac 10
);maxFactor
, there is fac x
, x must also be of typeclass Integral
, thus, maxFactor
's type would be begin with something like maxFactor :: (Integral a) => a ->
... then something else? However, if that is the case, then why this code compiles since the return of maxFactor
can be x
or head
, which when following this line of reasoning, does not have the same type?What am I missing here?
Thanks for any inputs in advance!
Upvotes: 11
Views: 653
Reputation: 1693
As you've noticed correctly, the use of function fac
inside of maxFactor
adds a Integral a
constraint on the type of x
. So x
needs to be of type Integral a => a
.
In addition, the compiler sees that maxFactor
either returns head
, which has type [a]->a
or x
. Therefore x
must have the more specific type Integral ([a]->a) => ([a]->a)
, and so maxFactor
has type
maxFactor :: Integral ([a] -> a) => ([a] -> a) -> ([a] -> a)
which is exactly what you got. There's nothing "wrong" with this definition so far. If you managed to write an instance of Integral
type ([a]->a)
you could invoke maxFactor
without problem. (Obviously maxFactor
wouldn't work as expected.)
Upvotes: 11
Reputation: 16635
in maxFactor
the compiler infers that the function argument x
necessarily has the same type as head
(in your if
clause). Since you also call fac
on x
(which in turn calls mod
) it infers that x
is also some Integral
class type. Consequently, the compiler infers the type
maxFactor :: Integral ([a] -> a) => ([a] -> a) -> [a] -> a
that takes some head
-like and integer-like argument... which is unlikely to be a real thing.
I think the fact that you can load that code into GHCi is more a quirk of the interpreter. If you were just compiling the code above, it would fail.
Edit: I guess the issue is that the type checker can make sense of your code, however there probably isn't any sensible way to use it.
Upvotes: 9