Home > Software design >  What's the type error in this expression `snd (True, [2,[5]])`?
What's the type error in this expression `snd (True, [2,[5]])`?

Time:11-13

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 [[(),()],[()]].

  • Related