2

Why doesn't the below type-check? The type of _ is inferred as Double.

{-# LANGUAGE ScopedTypeVariables, Rank2Types #-}

module Main (main) where

data D a = D a

main =
  let
    n = D (1 :: forall a. (Floating a) => a)
  in
    case n of
      D (_ :: forall a. (Floating a) => a) -> return ()
denormal
  • 273
  • 1
  • 8
  • 1
    Haskell does not support types like `D (forall a. (Floating a) => a)`, which is the type it looks like you actually want for `n` here, because that would require impredicative polymorphism. While `1` is indeed polymorphic here, `D 1` still defaults to `D Double` due to Haskell’s type defaulting rules (otherwise the type would be considered ambiguous). – Alexis King Jan 02 '17 at 18:58

1 Answers1

4

It appears that the type you are expecting for n is D (forall a. (Floating a) => a), but that is emphatically not the type that is inferred. In fact, if you try and add that type annotation to n, you will find that GHC will loudly complain. Such a type would require GHC to support impredicative polymorphism, and it currently does not (for more information on what that is and why it is complicated, see What is predicativity?).

The type that is actually inferred for n is D Double. This is actually the result of two things at play: the dreaded monomorphism restriction and Haskell’s type defaulting rules. Due to the monomorphism restriction, n must be inferred to be a monomorphic type (since it is not syntactically a function and does not have an explicit type annotation). For this reason, D 1 would be ambiguous, since 1 :: forall a. (Floating a) => a is polymorphic. However, in this case, Haskell has defaulting rules for numeric types, mostly to avoid the need to resolve ambiguities due to Haskell’s polymorphic number literals.

Since you have explicitly added a type annotation to 1 to make it Floating, then Haskell applies its default rule for floating-point types and defaults to Double. Therefore, the type of n is inferred to be D Double.

If you disable the monomorphism restriction, then the type of n would be the slightly more interesting type forall a. Floating a => D a, but that is the simpler universally quantified type rather than the existentially quantified one that you want.

Community
  • 1
  • 1
Alexis King
  • 43,109
  • 15
  • 131
  • 205