{-# LANGUAGE TypeFamilies, UndecidableSuperClasses, UndecidableInstances #-} module BidirectionalInstances where import Data.Constraint class Evidence a => Foo a where type Evidence a :: Constraint type Evidence a = () instance Foo Bool instance Foo Int instance Evidence (a, b) => Foo (a, b) where type Evidence (a, b) = (Foo a, Foo b) forwards :: Dict (Foo a) -> Dict (Foo b) -> Dict (Foo (a, b)) forwards Dict Dict = Dict backwards :: Dict (Foo (a, b)) -> (Dict (Foo a), Dict (Foo b)) backwards Dict = (Dict, Dict)