Functional Dependencies in System FC George Karachalias & Tom Schrijvers
Functional Dependencies vs. Associated Types
Functional Dependencies class Collection c e where empty :: c insert :: e -> c -> c ins2 x y col = insert x (insert y col) ins2 :: (Collection c e1, Collection c e2) => e1 -> e2 -> c -> c too general Mark P. Jones. Type Classes with Functional Dependencies
Functional Dependencies class Collection c e | c -> e where empty :: c insert :: e -> c -> c ins2 :: Collection c e => e -> e -> c -> c ins2 x y col = insert x (insert y col) Mark P. Jones. Type Classes with Functional Dependencies
Functional Dependencies (Instance) class Collection c e | c -> e where empty :: c insert :: e -> c -> c instance Collection [a] a where empty = [] insert x xs = (x:xs) Mark P. Jones. Type Classes with Functional Dependencies
Associated Types class Collection c where type Elem c empty :: c insert :: Elem c -> c -> c ins2 :: Collection c => Elem c -> Elem c -> c -> c ins2 x y col = insert x (insert y col) Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones. Associated Type Synonyms
Associated Types (Instance) class Collection c where type Elem c empty :: c insert :: Elem c -> c -> c instance Collection [a] where type Elem [a] = a empty = [] insert x xs = (x:xs) Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones. Associated Type Synonyms
FDs in System FC class C a b | a -> b instance C Int Bool f :: C Int b => b -> Bool f x = x
FDs in System FC class C a b | a -> b instance C Int Bool f :: C Int b => b -> Bool f x = x Couldn’t match expected type ‘Bool’ with actual type ‘b’
FDs in System FC class C a b | a -> b instance C Int Bool f :: C Int b => b -> Bool f x = x
FDs in System FC class C a b | a -> b instance C Int Bool f :: C Int b => b -> Bool f x = x (b ~ Bool)
ATs in System FC class C a where type F a instance C Int where type F Int = Bool f :: C Int => F Int -> Bool f x = x
“Death to Functional Dependencies Say I” - Simon Peyton Jones quote: https://ghc.haskell.org/trac/ghc/ticket/1614#comment:2 picture: https://i.ytimg.com/vi/2WgxPxxfT7E/maxresdefault.jpg
The Problem: Lack of Evidence
Lack of Evidence class C a b | a -> b instance C Int Bool f :: C Int b => b -> Bool f x = x data CDict a b = MkCDict cIntBool :: CDict Int Bool cIntBool = MkCDict f :: CDict Int b -> b -> Bool f d x = x
Translation of Functional Dependencies to Associated Types Tom Schrijvers, Martin Sulzmann, Simon PJ, Manuel Chakravarty. Towards Open Type Functions
Strategy Class Declarations Class Instances For every FD generate a new Associated Type For every FD add an equivalent equality in the context Class Instances For every FD generate an appropriate instance for the respective Associated Type Tom Schrijvers, Martin Sulzmann, Simon PJ, Manuel Chakravarty. Towards Open Type Functions
In Search of a Proof data Nat = Zero | Succ Nat class Add (x :: Nat) (y :: Nat) (z :: Nat) | x y -> z instance Add Zero m m instance Add n m k => Add (Succ n) m (Succ k)
In Search of a Proof class Add (x :: Nat) (y :: Nat) (z :: Nat) | x y -> z class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y }
In Search of a Proof class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y } instance Add Zero m m instance Add Zero m m where type Fd Zero m = ???
In Search of a Proof class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y } instance Add Zero m m instance Add Zero m m where type Fd Zero m = m
In Search of a Proof class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y } instance (Add n m k) => Add (Succ n) m (Succ k) instance (Add n m k) => Add (Succ n) m (Succ k) where type Fd (Succ n) m = ???
In Search of a Proof class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y } instance (Add n m k) => Add (Succ n) m (Succ k) instance (Add n m k) => Add (Succ n) m (Succ k) where type Fd (Succ n) m = Succ k
In Search of a Proof class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y } instance (Add n m k) => Add (Succ n) m (Succ k) instance (Add n m k) => Add (Succ n) m (Succ k) where type Fd (Succ n) m = Succ k k ~ Fd n m
In Search of a Proof class Fd x y ~ z => Add (x :: Nat) (y :: Nat) (z :: Nat) where { type Fd x y } instance (Add n m k) => Add (Succ n) m (Succ k) instance (Add n m k) => Add (Succ n) m (Succ k) where type Fd (Succ n) m = Succ (Fd n m)
FUNCTIONAL DEPENDENCIES From FDs to System FC FUNCTIONAL DEPENDENCIES ASSOCIATED TYPES TYPE CLASSES ADTs GADTs TYPE FAMILIES System FC
Bi-directional Instances Schrijvers, Tom and Sulzmann, Martin. Unified Type Checking for Type Classes and Type Families
Bi-directional Declarations class Eq a where (==) :: a -> a -> Bool class Eq a => Ord a where (>) :: a -> a -> Bool f :: Ord a => a -> a -> Bool f x y = (x == y) data EqD a = MkEqD { (==) :: a -> a -> Bool } data OrdD a = MkOrdD { (>) :: a -> a -> Bool eqd :: EqD a } f :: OrdD a -> a -> a -> Bool f d x y = (==) (eqd d) x y
Non-Bi-directional Instances class Eq a where (==) :: a -> a -> Bool instance Eq a => Eq [a] where x == y = all (zipWith (==) x y) data EqD a = MkEqD { (==) :: a -> a -> Bool } eqList :: EqD a -> EqD [a] eqList d = MkEqD { (==) = \x y -> all (zipWith ((==) d) x y
FDs vs. Type Families data Nat = Zero | Succ Nat data Vec :: Nat -> * -> * where VN :: Vec Zero a VC :: a -> Vec n a -> Vec (Succ n) a
FDs vs. Type Families type family Add (x :: Nat) (y :: Nat) :: Nat type instance Add Zero m = m type instance Add (Succ n) m = Succ (Add n m) append :: Vec n a -> Vec m a -> Vec (Add n m) a append VN ys = ys append (VC x xs) ys = VC x (append xs ys)
FDs vs. Type Families class Add (x :: Nat) (y :: Nat) (z :: Nat) | x y -> z instance Add Zero m m instance Add n m k => Add (Succ n) m (Succ k) append :: Add n m k => Vec n a -> Vec m a -> Vec k a append VN ys = ys append (VC x xs) ys = VC x (append xs ys)
Thank You!
Functional Dependencies in System FC George Karachalias & Tom Schrijvers