[GHC] #15869: Discrepancy between seemingly equivalent type synonym and type family
GHC
ghc-devs at haskell.org
Fri Jan 18 15:58:17 UTC 2019
#15869: Discrepancy between seemingly equivalent type synonym and type family
-------------------------------------+-------------------------------------
Reporter: RyanGlScott | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (Type | Version: 8.6.2
checker) | Keywords: TypeFamilies,
Resolution: | TypeInType
Operating System: Unknown/Multiple | Architecture:
Type of failure: GHC rejects | Unknown/Multiple
valid program | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Description changed by RyanGlScott:
Old description:
> Consider the following code:
>
> {{{#!hs
> {-# LANGUAGE DataKinds #-}
> {-# LANGUAGE ImpredicativeTypes #-}
> {-# LANGUAGE PolyKinds #-}
> {-# LANGUAGE TypeFamilies #-}
>
> {-# LANGUAGE TypeInType #-}
> module Bug where
>
> import Data.Kind
>
> type KindOf1 (a :: k) = k
> type family KindOf2 (a :: k) :: Type where
> KindOf2 (a :: k) = k
>
> data A (a :: Type) :: a -> Type
> type family Apply1 (f :: KindOf1 A) (a :: Type) (x :: a) :: Type where
> Apply1 f a x = f a x
> }}}
>
> `Apply1` kind-checks, which is just peachy. Note that `Apply1` uses
> `KindOf1`, which is a type synonym. Suppose I wanted to swap out
> `KindOf1` for `KindOf2`, which is (seemingly) an equivalent type family.
> I can define this:
>
> {{{#!hs
> type family Apply2 (f :: KindOf2 A) -- (f :: forall a -> a -> Type)
> (a :: Type)
> (x :: a)
> :: Type where
> Apply2 f a x = f a x
> }}}
>
> However, GHC rejects this!
>
> {{{
> $ /opt/ghc/8.6.2/bin/ghc Bug.hs
> [1 of 1] Compiling Bug ( Bug.hs, Bug.o )
>
> Bug.hs:25:10: error:
> • Expecting two more arguments to ‘f’
> Expected kind ‘KindOf2 A’, but ‘f’ has kind ‘* -> a -> *’
> • In the first argument of ‘Apply2’, namely ‘f’
> In the type family declaration for ‘Apply2’
> |
> 25 | Apply2 f a x = f a x
> | ^
> }}}
>
> I find this quite surprising, since I would have expected `KindOf1` and
> `KindOf2` to be functionally equivalent. Even providing explicit
> `forall`s does not make it kind-check:
>
> {{{#!hs
> type family Apply2 (f :: KindOf2 A) -- (f :: forall a -> a -> Type)
> (a :: Type)
> (x :: a)
> :: Type where
> forall (f :: KindOf2 A) (a :: Type) (x :: a).
> Apply2 f a x = f a x
> }}}
>
> Although the error message does change a bit:
>
> {{{
> $ ~/Software/ghc3/inplace/bin/ghc-stage2 Bug.hs
> [1 of 1] Compiling Bug ( Bug.hs, Bug.o )
>
> Bug.hs:26:20: error:
> • Expected kind ‘* -> a -> *’, but ‘f’ has kind ‘KindOf2 A’
> • In the type ‘f a x’
> In the type family declaration for ‘Apply2’
> |
> 26 | Apply2 f a x = f a x
> | ^^^^^
> }}}
New description:
Consider the following code:
{{{#!hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE LiberalTypeSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
module Bug where
import Data.Kind
type KindOf1 (a :: k) = k
type family KindOf2 (a :: k) :: Type where
KindOf2 (a :: k) = k
data A (a :: Type) :: a -> Type
type family Apply1 (f :: KindOf1 A) (a :: Type) (x :: a) :: Type where
Apply1 f a x = f a x
}}}
`Apply1` kind-checks, which is just peachy. Note that `Apply1` uses
`KindOf1`, which is a type synonym. Suppose I wanted to swap out `KindOf1`
for `KindOf2`, which is (seemingly) an equivalent type family. I can
define this:
{{{#!hs
type family Apply2 (f :: KindOf2 A) -- (f :: forall a -> a -> Type)
(a :: Type)
(x :: a)
:: Type where
Apply2 f a x = f a x
}}}
However, GHC rejects this!
{{{
$ /opt/ghc/8.6.2/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
Bug.hs:25:10: error:
• Expecting two more arguments to ‘f’
Expected kind ‘KindOf2 A’, but ‘f’ has kind ‘* -> a -> *’
• In the first argument of ‘Apply2’, namely ‘f’
In the type family declaration for ‘Apply2’
|
25 | Apply2 f a x = f a x
| ^
}}}
I find this quite surprising, since I would have expected `KindOf1` and
`KindOf2` to be functionally equivalent. Even providing explicit `forall`s
does not make it kind-check:
{{{#!hs
type family Apply2 (f :: KindOf2 A) -- (f :: forall a -> a -> Type)
(a :: Type)
(x :: a)
:: Type where
forall (f :: KindOf2 A) (a :: Type) (x :: a).
Apply2 f a x = f a x
}}}
Although the error message does change a bit:
{{{
$ ~/Software/ghc3/inplace/bin/ghc-stage2 Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
Bug.hs:26:20: error:
• Expected kind ‘* -> a -> *’, but ‘f’ has kind ‘KindOf2 A’
• In the type ‘f a x’
In the type family declaration for ‘Apply2’
|
26 | Apply2 f a x = f a x
| ^^^^^
}}}
--
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15869#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list