{-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} {- | Module: Control.Bidirectional.Class Description: Base types for bidirectional instances Copyright: Lev Dvorkin (c) 2022 License: MIT Maintainer: lev_135@mail.ru Stability: experimental -} module Control.Bidirectional.Class ( Bidirectional (..), BidirectionalRec (..) ) where import Data.Kind (Constraint) {-| Class for non-recursive bidirectional instances, i. e. for instances, such that their components constraints ('Constr') is ordinary instance. Arguments: - @c@ class for which we declare bidirectional instance - @a@ data type for which instance is provided For example: > instance Show a => Bidirectional Show [a] where > type ConstrRec Show [a] = Show a is correct 'Bidirectional' instance. If you want to have bidirectional 'Show' instance in backward constraint, use 'BidirectionalRec' Instances for this class are supposed to be generated by 'Control.Bidirectional.makeBidirectionalInstances` or by 'Control.Bidirectional.decBidirectionalInstances`. -} class (c a, Constr c a) => Bidirectional (c :: k -> Constraint) (a :: k) where -- | Constraint for backwards inference. -- Should not be recursively bidirectional (it means that all constraints -- should not be wrapped in 'Bidirectional', e. g. @Show a@ but not -- @Bidirectional Show a@) type Constr c a :: Constraint {-| Class for recursive bidirectional instances, i. e. for instances, such that components also have bidirectional instance. Use 'Bidirectional' non-recursive variant, if you need only one step in backward direction. Arguments: - @c@ class for which we declare bidirectional instance - @a@ data type for which instance is provided For example, this is a nice recursive instance: > instance BidirectionalRec Show a => BidirectionalRec Show [a] where > type ConstrRec Show [a] = BidirectionalRec Show a but this one isn't (actually it should be a 'Bidirectional' instance): > instance Show a => BidirectionalRec Show [a] where > type ConstrRec Show [a] = Show a Instances for this class are supposed to be generated by 'Control.Bidirectional.makeBidirectionalInstances` or by 'Control.Bidirectional.decBidirectionalInstances`. -} class (c a, ConstrRec c a, Bidirectional c a) => BidirectionalRec (c :: k -> Constraint) (a :: k) where -- | Constraint for backwards inference. -- Should be recursively bidirectional (it means that all constraints should -- be wrapped in 'BidirectionalRec', e. g. @BidirectionalRec Show a@ but not -- simply @Show a@) type ConstrRec c a :: Constraint