The language report does not allow instances of the form instance Class a where...
, so the only way to avoid FlexibleInstances
(which is not at all scary) is to use the newtype shell,
newtype LinearType a = Linear a liftLin2 :: (a -> b -> c) -> LinearType a -> LinearType b -> LinearType c liftLin2 op (Linear x) (Linear y) = Linear (op xy) instance Num a => Linear (LinearType a) where add = liftLin2 (+)
Ugh.
The extension UndecidableInstances
necessary because the restriction of Num a
not less than the head of the instance (it uses the same type of variables the same number of times), so the compiler cannot prove in advance that type checking will stop. Therefore, you must promise the compiler that the type check is completed so that it can accept the program (in fact, it will not work with GHC, which has a context stack that controls the depth of the type check recursion, so if type checking does not work, t finish soon enough, this will cause compilation to fail with "exceeding the context stack" - you can set the size with -fcontext-stack=N
).
This extension sounds a lot worse than it is. Basically, all he does is tell the compiler "Believe me, type checking will end", so the compiler will start, not knowing for sure what it will finish.
But what are you trying to achieve? What do you have,
instance (Num a) => Linear a where add = (+)
says that "each type is an instance of Linear, and if you try to use add in a type, and not in a Num instance, this is a compile-time error." This is not very helpful. You cannot add additional instances for non- Num
types unless you also include OverlappingInstances
and possibly IncoherentInstances
. And these extensions are scary, they need to be used hardly and only when you know what you are doing.
source share