Skip to content

Deep subsumption does not instantiate in cases where it should

See also:

There are many situations in which one would expect deep subsumption to allow a program to be accepted, yet it doesn't.

Here follows a collection of examples. I've used partial type signatures for simplicity, but the same errors can be triggered without it. Examples ex1', ex2', ex3 and ex3' are all incorrectly rejected.

{-# LANGUAGE DeepSubsumption #-}
{-# LANGUAGE NamedWildCards #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnicodeSyntax #-}

{-# OPTIONS_GHC -Wno-partial-type-signatures #-}

module T26225 where

-- Recall: ty1 is a subtype of ty2, written ty1 ⊑ ty2,
--         if we can use ty1 wherever ty2 is expected.
-- Example: ∀ a. a -> a  ⊑  Int -> Int, meaning that we can pass
--          the identity function where one is expecting a function of type Int -> Int.

-- Int -> (∀ a. a -> a)  ⊑  α[tau]
-- Accepted by GHC.
ex0 :: ()
ex0 =
  let
    f :: Int -> ( a. a -> a)
    f _ = id
    g :: _α -> ()
    g _ = ()
  in g f

-- ((∀ a. a->a) -> Int) -> Bool  ⊑  α[tau]
-- Rejected by GHC up to and including 9.14.
ex1' :: ()
ex1' =
  let
    f :: (( a. a -> a) -> Int) -> Bool
    f _ = False
    g :: _α -> ()
    g _ = ()
  in g f
    -- Couldn't match expected type ‘α’ with actual type ‘((∀ a. a -> a) -> Int) -> Bool’

-- ((∀ a. a->a) -> Int) -> Bool  ⊑  β[tau] Bool
-- Rejected by GHC up to and including 9.14.
ex2' :: ()
ex2' =
  let
    f :: (( a. a -> a) -> Int) -> Bool
    f _ = False
    g :: _β Bool -> ()
    g _ = ()
  in g f
    -- Couldn't match expected type ‘β’ with actual type ‘(->) ((∀ a. a -> a) -> Int)’

-- ex3 :: β[tau] Bool  ⊑  (∀ a. a->a) -> Bool
-- Rejected by GHC up to and including 9.14.
ex3 :: ()
ex3 =
  let
    f :: _β Bool
    f = undefined
    g :: (( a. a -> a) -> Bool) -> ()
    g _ = ()
  in g f
    -- Couldn't match expected type ‘β’ with actual type ‘(->) (∀ a. a -> a)’

-- ex3' :: F Int Bool  ⊑  (∀ a. a->a) -> Bool, where F Int = (->) (Int -> Int)
-- Rejected by GHC up to and including 9.14.
ex3' :: ()
ex3' =
  let
    f :: F Int Bool
    f _ = False
    g :: (( a. a -> a) -> Bool) -> ()
    g _ = ()
  in g f
    -- • Couldn't match type: Int -> Int
    --             with: ∀ a. a -> a
    --   Expected: (∀ a. a -> a) -> Bool
    --     Actual: F Int Bool
type family F a where { F Int = (->) (Int -> Int) }
Edited by Simon Peyton Jones
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information