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

import Data.Set

class Suitable m a where
   data Constraints m a
   constraints :: m a -> Constraints m a

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

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

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

instance Suitable Maybe a where
   data Constraints Maybe a = MaybeConstraints
   constraints _ = MaybeConstraints

instance Suitable [] a where
   data Constraints [] a = ListConstraints
   constraints _ = ListConstraints

instance Suitable IO a where
   data Constraints IO a = IOConstraints
   constraints _ = IOConstraints

instance Ord a => Suitable Set a where
   data Constraints Set a = Ord a => SetConstraints
   constraints _ = SetConstraints