Skip to content

Invalid type applications cause unrelated valid code to error

Summary

Certain invalid type applications cause otherwise cleanly-compiling code to error

Steps to reproduce

Consider the following code:

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilyDependencies #-}

import Data.List (sort)

adapt :: forall a c. c a => (forall m. (Eq m, c m) => m -> Bool) -> a -> Bool
adapt f = f @(Maybe a) @Ord

{-# ANN myid "break" #-}
myid :: a -> a
myid x = x

type Sorted :: (* -> *) -> (* -> *)
type family Sorted f = r | r -> f

class Sort f where
  mkSorted :: Ord x => f x -> Sorted f x

newtype SortedList a = SortedList [a]

type instance Sorted [] = SortedList

instance Sort [] where
  mkSorted = SortedList . sort

In the presence of both adapt and myId, GHC complains:

[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:10:11: error:
    • Cannot apply expression of type ‘Maybe a -> Bool’
      to a visible type argument ‘Ord’
    • In the expression: f @(Maybe a) @Ord
      In an equation for ‘adapt’: adapt f = f @(Maybe a) @Ord
   |
10 | adapt f = f @(Maybe a) @Ord
   |           ^^^^^^^^^^^^^^^^^

test.hs:10:11: error:
    • Could not deduce: c (Maybe a) arising from a use of ‘f’
    • In the expression: f @(Maybe a) @Ord
      In an equation for ‘adapt’: adapt f = f @(Maybe a) @Ord
    • Relevant bindings include
        f :: forall m. (Monoid m, c m) => m -> Bool (bound at test.hs:10:7)
        adapt :: (forall m. (Monoid m, c m) => m -> Bool) -> a -> Bool
          (bound at test.hs:10:1)
   |
10 | adapt f = f @(Maybe a) @Ord
   |           ^^^^^^^^^^^^^^^^^

test.hs:27:14: error:
    • Couldn't match type ‘Sorted []’ with ‘SortedList’
      Expected: [x] -> Sorted [] x
        Actual: [x] -> SortedList x
    • In the expression: SortedList . sort
      In an equation for ‘mkSorted’: mkSorted = SortedList . sort
      In the instance declaration for ‘Sort []’
   |
27 |   mkSorted = SortedList . sort
   |              ^^^^^^^^^^^^^^^^^
Failed, no modules loaded.

However, if adapt is removed, GHC has no complaints. More confusing, if myid is removed GHC doesn't complain about mkSorted.

Expected behavior

Considering adapt and the Sorted/Sort parts are completely independent, errors in one should at most suppress errors in the other due to higher priority, not create errors where there are none.

Environment

  • GHC version used: 9.0.1
Edited by Gesh
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information