{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, ScopedTypeVariables, FlexibleInstances #-}
module Data.Suitable (Suitable(..), Constraints(..), withResConstraints, withConstraintsOf) where

import Data.Set

data family Constraints (m :: * -> *) :: * -> *

class Suitable m a where
   constraints :: Constraints m a

withResConstraints :: Suitable m a => (Constraints m a -> m a) -> m a
withResConstraints f = f constraints

withConstraintsOf :: Suitable m a => m a -> (Constraints m a -> k) -> k
withConstraintsOf _ f = f constraints


data instance Constraints ((->) r) a = FuncConstraints

instance Suitable ((->) r) a where
   constraints = FuncConstraints


data instance Constraints Maybe a = MaybeConstraints

instance Suitable Maybe a where
   constraints = MaybeConstraints

data instance Constraints [] a = ListConstraints

instance Suitable [] a where
   constraints = ListConstraints


data instance Constraints IO a = IOConstraints

instance Suitable IO a where
   constraints = IOConstraints


data instance Constraints Set a = Ord a => SetConstraints

instance Ord a => Suitable Set a where
   constraints = SetConstraints