5

In GHCi, i type

let xs = [1, 'a']

it complains the error immediately:

<interactive>:28:11:
No instance for (Num Char) arising from the literal ‘1’
In the expression: 1
In the expression: [1, 'a']
In an equation for ‘xs’: xs = [1, 'a']

However, when I type

let xs = [1, [1, 1]]

It just passed. And it complains when I try to print xs:

<interactive>:5:1:
No instance for (Num [t0]) arising from a use of ‘it’
In a stmt of an interactive GHCi command: print it

I think Haskell is a static type language so any type error should be caught in compile time. I am wondering why the above 2 errors are caught at different time?

0

1 Answer 1

8

1 is a polymorphic value of type Num a => a. So in [1, [2, 3]], we have [2, 3] :: Num a => [a]; since all list elements must have the same type, we conclude that we must have 1 :: Num a => [a]. That's a bit weird -- it's odd to think of 1 as having a list type -- but can be perfectly valid if somebody creates a sufficiently weird instance of Num. Checking whether an instance exists is pushed off until you try to use the instance; this gives you a chance to define the instance after you've defined the value using the instance. So it doesn't complain until you try to actually do something with the list [1, [2, 3]].

Just to illustrate what I mean, one may write:

instance Num a => Num [a] where
    fromInteger n = pure (fromInteger n)
    (+) = liftA2 (+)
    (-) = liftA2 (-)
    (*) = liftA2 (*)
    abs    = liftA abs
    signum = liftA signum

(Indeed, this instance works for any Applicative, and is occasionally even useful.) Then, in ghci:

> let xs = [1, [1, 1]]
> xs
[[1],[1,1]]

See ma, no errors!

Sign up to request clarification or add additional context in comments.

5 Comments

Why doesn't the same reasoning apply to a potential Num Char instance though?
@ReidBarton Good question! I'm actually not sure about that. I would guess that during instance resolution, GHC refuses to delay finding evidence for monomorphic constraints; but that's just a guess.
You could define a Num Char instance based on the Enum Char instance. The same reasoning would apply, but the instance just isn't included here.
@DanielWagner, sounds plausible, and I guess the reason why it does not eagerly solve the constraint in the polymorphic case is not because you might define an instance Num [a] later (same is true for Num Char), but because (with FlexibleInstances) there might be some specific instances like Num [Double], and then you could use xs at type [[Double]]. In other words, GHC doesn't know what constraint to try to solve yet.
This is kind of toooo deep for me, I am just a beginner in FP....takes time to digest your answer. Anyway, thanks a billion....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.