When I evaluate the expression,
snd (True, [2,[5]])
the compiler says:
• Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Num a, Num [a]) => [[a]]
How can I solve it ? For me, snd
should work on any tuple type based on its signature, but perhaps that is not the case.
CodePudding user response:
The problem is the expression [2,[5]]
. It's invalid for the same reason that ['x',True]
is invalid: in Haskell, all elements of a list must be of the same type.
The reason you got a cryptic error message from [2,[5]]
instead of the simple error message Couldn't match expected type ‘Char’ with actual type ‘Bool’
that ['x',True]
yields is that numeric literals in Haskell are polymorphic, so if you had a really weird (and probably unlawful) Num
instance in scope, then it would be technically possible to create and use such a type; it just almost certainly wouldn't do what you wanted.
Just for fun, here's a case where what you wrote would be valid (and the instances are even lawful):
{-# LANGUAGE ExtendedDefaultRules, FlexibleContexts, FlexibleInstances #-}
instance Num () where
_ _ = ()
_ * _ = ()
abs _ = ()
signum _ = ()
fromInteger _ = ()
_ - _ = ()
instance Num [()] where
( ) = ( )
(*) = (*>)
abs = id
signum _ = [()]
fromInteger x
| x >= 0 = replicate (fromInteger x) ()
| otherwise = error "if Natural can bottom here, so can this"
xs - [] = xs
(_:xs) - (_:ys) = xs - ys
[] - (_:_) = error "if Natural can bottom here, so can this"
main :: IO ()
main = print $ snd (True, [2,[5]])
It prints [[(),()],[()]]
.