The problem is that literal 200 interpreted differently in two different contexts with your first example. Think of it as
((:) :: a -> [a] -> [a]) ((coerceInteger :: Integer -> Integer) (literal 100 :: Expr a => a)) (literal 100 :: Expr a => a)
Just based on types, the compiler determines that the first literal 100 must be of type Integer , because it is passed to coerceInteger , since it must be of type Integer . This also sets the type (:) now Integer -> [Integer] -> [Integer] , implying that the last literal 100 must be of type [Integer] .
In the second example, you say that both of them have the same value and, therefore, the same type, which is impossible, because the second must be a list for (:) to check the type.
This is actually due to the terrible restriction of monomorphism. You can fix this problem in two ways: one, disable monomorphism restriction using {-# LANGUAGE NoMonomorphismRestriction #-} , or you can provide an explicit expr type that will generalize it:
main :: IO () main = print $ coerceInteger expr : expr where expr :: Expr a => a expr = literal 100
Any of these approaches work, and whatever you decide to do, I would recommend always providing type signatures to avoid these problems.
In fact, once you add a type signature, you can even do things like
main :: IO () main = print $ coerceInteger expr : expr : expr : expr : expr : expr where expr :: Expr a => a expr = literal 100
no problem, it will print [100, 100, 100, 100, 100, 100] . The initial coerceInteger needed because otherwise the compiler will not know what to create, and therefore will not have a Show instance for print .