{-# language TypeFamilies, DataKinds, UndecidableInstances, TypeFamilyDependencies, QuantifiedConstraints #-} module M where import GHC.TypeLits import Data.Type.Equality import Data.Kind data FArray (n :: Nat) instance Num (FArray n) class Tensor r where type TensorOf (n :: Nat) r = t | t -> n r type IntOf r type family BooleanOf r instance Tensor Float where type TensorOf n Float = FArray n type IntOf Float = Int type instance BooleanOf Int = Bool type instance BooleanOf (FArray n) = Bool class (forall y. c (TensorOf y r)) => CRanked c r where instance (forall y. c (TensorOf y r)) => CRanked c r where {- class (b ~ BooleanOf r) => BooleanOfMatches b r where instance (b ~ BooleanOf r) => BooleanOfMatches b r where -} class (BooleanOf r ~ b) => BooleanOfMatches b r where instance (BooleanOf r ~ b) => BooleanOfMatches b r where type BundleOfConstraints r = (Num r, CRanked (BooleanOfMatches (BooleanOf (IntOf r))) r) foo :: (BundleOfConstraints r, Eq (BooleanOf (IntOf r))) => BooleanOf (IntOf r) -> BooleanOf (TensorOf n r) -> TensorOf n r -> TensorOf n r foo b1 b2 r = if b1 == b2 then r else r bar :: FArray n -> FArray n bar x = foo undefined undefined x