Skip to content

untouchable type inside the constraints

The following code is taken and simplified from the test-suite of accelerate-fourier:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE Rank2Types #-}
module UntouchableType (tests) where

import Test.QuickCheck (Testable, Arbitrary, arbitrary, quickCheck, )


newtype Sign a = Sign a
   deriving (Show)

instance Arbitrary (Sign a) where
   arbitrary = undefined

quickCheckWithSign :: (Testable prop) => (Sign Double -> prop) -> IO ()
quickCheckWithSign = quickCheck


data Array sh a = Array

type family FullShape sh :: *

data SubTransform a =
        SubTransform (forall sh. (FullShape sh ~ sh) => Array sh a)

transform2d :: SubTransform Double -> Bool
transform2d = undefined

transformChirp2 :: Sign a -> Array sh a
transformChirp2 = undefined


tests :: IO ()
tests =
   quickCheck $ \sign ->
      transform2d (SubTransform (transformChirp2 (sign::Sign Double)))

GHC-8.2.2 says about it:

[1 of 1] Compiling UntouchableType  ( UntouchableType.hs, interpreted )

UntouchableType.hs:34:4: error:
    • Ambiguous type variable ‘p0’ arising from a use of ‘quickCheck’
      prevents the constraint ‘(Arbitrary p0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘p0’ should be.
      These potential instances exist:
        instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
          -- Defined in ‘Test.QuickCheck.Arbitrary’
        instance Arbitrary Ordering
          -- Defined in ‘Test.QuickCheck.Arbitrary’
        instance Arbitrary Integer
          -- Defined in ‘Test.QuickCheck.Arbitrary’
        ...plus 20 others
        ...plus 62 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression:
        quickCheck
          $ \ sign
              -> transform2d
                   (SubTransform (transformChirp2 (sign :: Sign Double)))
      In an equation for ‘tests’:
          tests
            = quickCheck
                $ \ sign
                    -> transform2d
                         (SubTransform (transformChirp2 (sign :: Sign Double)))
   |
34 |    quickCheck $ \sign ->
   |    ^^^^^^^^^^^^^^^^^^^^^...

UntouchableType.hs:35:51: error:
    • Couldn't match expected type ‘Sign Double’ with actual type ‘p0’
        ‘p0’ is untouchable
          inside the constraints: FullShape sh ~ sh
          bound by a type expected by the context:
                     forall sh. FullShape sh ~ sh => Array sh Double
          at UntouchableType.hs:35:20-69
    • In the first argument of ‘transformChirp2’, namely
        ‘(sign :: Sign Double)’
      In the first argument of ‘SubTransform’, namely
        ‘(transformChirp2 (sign :: Sign Double))’
      In the first argument of ‘transform2d’, namely
        ‘(SubTransform (transformChirp2 (sign :: Sign Double)))’
    • Relevant bindings include
        sign :: p0 (bound at UntouchableType.hs:34:18)
   |
35 |       transform2d (SubTransform (transformChirp2 (sign::Sign Double)))
   |                                                   ^^^^
Failed, no modules loaded.

I have tested GHC versions back to GHC-7.4.2, all of them report essentially the same type error.

I do not really understand the type error message, but here are my observations that I find strange: The type annotation sign :: Sign Double does not prevent the type error, but replacing quickCheck by quickCheckWithSign does. Replacing the constraint FullShape sh ~ sh by, e.g. Show sh, let the error disappear. Generalizing transform2d to SubTransform a causes another type error although I expected that SubTransform Double can be infered from Sign Double.

Trac metadata
Trac field Value
Version 8.2.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (Type checker)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information