{-# 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