Why is a function type required to be "wrapped" for the type checker to be satisfied?

Viewed 129

The following program type-checks:

{-# LANGUAGE RankNTypes #-}

import Numeric.AD (grad)

newtype Fun = Fun (forall a. Num a => [a] -> a)

test1 [u, v] = (v - (u * u * u))
test2 [u, v] = ((u * u) + (v * v) - 1)

main = print $ fmap (\(Fun f) -> grad f [1,1]) [Fun test1, Fun test2]

But this program fails:

main = print $ fmap (\f -> grad f [1,1]) [test1, test2]

With the type error:

Grad.hs:13:33: error:
    • Couldn't match type ‘Integer’
                     with ‘Numeric.AD.Internal.Reverse.Reverse s Integer’
      Expected type: [Numeric.AD.Internal.Reverse.Reverse s Integer]
                     -> Numeric.AD.Internal.Reverse.Reverse s Integer
        Actual type: [Integer] -> Integer
    • In the first argument of ‘grad’, namely ‘f’
      In the expression: grad f [1, 1]
      In the first argument of ‘fmap’, namely ‘(\ f -> grad f [1, 1])’

Intuitively, the latter program looks correct. After all, the following, seemingly equivalent program does work:

main = print $ [grad test1 [1,1], grad test2 [1,1]]

It looks like a limitation in GHC's type system. I would like to know what causes the failure, why this limitation exists, and any possible workarounds besides wrapping the function (per Fun above).

(Note: this is not caused by the monomorphism restriction; compiling with NoMonomorphismRestriction does not help.)

2 Answers
Related