{-# LANGUAGE TypeFamilies, DataKinds, PolyKinds, UndecidableInstances #-}
module T6018failclosed where
-- Id is injective...
type family IdClosed a = result | result -> a where
IdClosed a = a
-- ...but despite that we disallow a call to Id
type family IdProxyClosed (a :: *) = r | r -> a where
IdProxyClosed a = IdClosed a
data N = Z | S N
-- PClosed is not injective, although the user declares otherwise. This
-- should be rejected on the grounds of calling a type family in the
-- RHS.
type family PClosed (a :: N) (b :: N) = (r :: N) | r -> a b where
PClosed Z m = m
PClosed (S n) m = S (PClosed n m)
-- this is not injective - not all injective type variables mentioned
-- on LHS are mentioned on RHS
type family JClosed a b c = r | r -> a b where
JClosed Int b c = Char
-- this is not injective - not all injective type variables mentioned
-- on LHS are mentioned on RHS (tyvar is now nested inside a tycon)
type family KClosed (a :: N) (b :: N) = (r :: N) | r -> a b where
KClosed (S n) m = S m
-- hiding a type family application behind a type synonym should be rejected
type MaybeSynClosed a = IdClosed a
type family LClosed a = r | r -> a where
LClosed a = MaybeSynClosed a
type family FClosed a b c = (result :: *) | result -> a b c where
FClosed Int Char Bool = Bool
FClosed Char Bool Int = Int
FClosed Bool Int Char = Int
type family IClosed a b c = r | r -> a b where
IClosed Int Char Bool = Bool
IClosed Int Int Int = Bool
IClosed Bool Int Int = Int
type family E2 (a :: Bool) = r | r -> a where
E2 False = True
E2 True = False
E2 a = False
-- This exposed a subtle bug in the implementation during development. After
-- unifying the RHS of (1) and (2) the LHS substitution was done only in (2)
-- which made it look like an overlapped equation. This is not the case and this
-- definition should be rejected. The first two equations are here to make sure
-- that the internal implementation does list indexing corrcectly (this is a bit
-- tricky because the list is kept in reverse order).
type family F a b = r | r -> a b where
F Float IO = Float
F Bool IO = Bool
F a IO = IO a -- (1)
F Char b = b Int -- (2)
-- This should fail because there is no way to determine a, b and k from the RHS
type family Gc (a :: k) (b :: k) = r | r -> k where
Gc a b = Int