I've got some code that compiles:
{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs,
FlexibleContexts #-}
module Foo where
data Foo :: (* -> *) where
Foo :: c m zp' -> Foo (c m zp)
f :: forall c m zp d . Foo (c m zp) -> d
f y@(Foo (x :: c m a)) = g x y
g :: c m a -> Foo (c m b) -> d
g = error ""
The key thing I need in my real code is to convince GHC that if y
has the type Foo (c m zp)
and x
has the type c' m' zp'
, then c' ~ c
and m' ~ m
. The above code achieves this because I am able to call g
.
I want to change this code in two orthogonal ways, but I can't seem to figure out how to make GHC compile the code with either change.
First change: Add -XPolyKinds
. GHC 7.8.3 complains:
Foo.hs:10:11:
Could not deduce ((~) (k2 -> k3 -> *) c1 c)
from the context ((~) * (c m zp) (c1 m1 zp1))
bound by a pattern with constructor
Foo :: forall (k :: BOX)
(k :: BOX)
(c :: k -> k -> *)
(m :: k)
(zp' :: k)
(zp :: k).
c m zp' -> Foo (c m zp),
in an equation for ‘f’
at Foo.hs:10:6-21
‘c1’ is a rigid type variable bound by
a pattern with constructor
Foo :: forall (k :: BOX)
(k :: BOX)
(c :: k -> k -> *)
(m :: k)
(zp' :: k)
(zp :: k).
c m zp' -> Foo (c m zp),
in an equation for ‘f’
at Foo.hs:10:6
‘c’ is a rigid type variable bound by
the type signature for f :: Foo (c m zp) -> d
at Foo.hs:9:13
Expected type: c1 m1 zp'
Actual type: c m a
Relevant bindings include
y :: Foo (c m zp) (bound at Foo.hs:10:3)
f :: Foo (c m zp) -> d (bound at Foo.hs:10:1)
In the pattern: x :: c m a
In the pattern: Foo (x :: c m a)
In an equation for ‘f’: f y@(Foo (x :: c m a)) = g x y
Foo.hs:10:11:
Could not deduce ((~) k2 m1 m)
from the context ((~) * (c m zp) (c1 m1 zp1))
...
Second change: Forget about -XPolyKinds
. Instead I want to use -XDataKinds
to create a new kind and restrict the kind of m
:
{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs,
FlexibleContexts, DataKinds #-}
module Foo where
data Bar
data Foo :: (* -> *) where
Foo :: c (m :: Bar) zp' -> Foo (c m zp)
f :: forall c m zp d . Foo (c m zp) -> d
f y@(Foo (x :: c m a)) = g x y
g :: c m a -> Foo (c m b) -> d
g = error ""
I get similar errors (can't deduce (c1 ~ c)
, can't deduce (m1 ~ m)
).
DataKinds
seems to be relevant here: if I restrict m
to have kind Constraint
instead of kind Bar
, the code compiles fine.
I've given two examples of how to break the original code, both of which use higher-kinded types. I've tried using case statements instead of pattern guards, I've tried giving a type to node
instead of x
, my usual tricks aren't working here.
I'm not picky about where the type for x
ends up/what it looks like, I just need to be able to convince GHC that if y
has the type Foo (c m zp)
, then x
has the type c m zp'
for some unrelated type zp'
.
x
andy
,zp
andzp'
are completely unrelated types. You have mentionedzp
in the type signature of the function, butzp'
is mentioned nowhere else. How can you expect the compiler to infer some relation between them? – user2407038c
andm
to be the same. – crockeeag
doesn't work inf
with the provided type. It does work inf
withg :: ASTF dom (c m a) -> ASTF dom (c m b) -> ASTF dom (c m b)
. The type ofg
is suspiciously similar to the type off
; it doesn't convince me that there are any interesting functions that require this proof. – Cirdec