{-#LANGUAGE FlexibleContexts,MultiParamTypeClasses,FlexibleInstances,UndecidableInstances #-} module PrivLib ( getFoo, putFoo, runFoo, TyFoo, runFooT, TyFooT, MonadFoo(..) ) where import Control.Monad.StateX -- create the private index. do not export. data PRIV = PRIV deriving (Show,Eq); instance Index PRIV where getVal = PRIV -- create `wrapper' functions for all monadic behavior you want to -- allow. This part is the most annoying. getFoo :: (MonadStateX PRIV s m) => m s getFoo = getx PRIV putFoo :: (MonadStateX PRIV s m) => s -> m () putFoo = putx PRIV -- create type synonyms to give controlled access. export. type TyFoo s a = StateX PRIV s a type TyFooT s m a = StateTX PRIV s m a runFoo start = flip (runStateX PRIV) start runFooT start = flip (runStateTX PRIV) start -- create an empty type class only to `rename' the constraint without -- having to reference the private index. class (MonadStateX PRIV s m) => MonadFoo s m where instance (MonadStateX PRIV s m) => MonadFoo s m where -- No Quadratic-sized set of instances to add, and yet you have -- removed direct acces to the index! Safety is argued. Again, all the -- `dangerous' pragmas are only needed in this file: -- FlexibleInstances, UndecidableInstances. {- class (Monad m) => {-(MonadStateX PRIV s m) => -} MonadFoo s m where getFoo :: m s putFoo :: s -> m () instance (s1 ~ s2) => MonadFoo s1 (StateX PRIV s2) where getFoo = getx PRIV putFoo = putx PRIV instance (Monad m, s1 ~ s2) => MonadFoo s1 (StateTX PRIV s2 m) where getFoo = getx PRIV putFoo = putx PRIV -} -- this gets an interesting type families nonsupported usage error. --class (MonadStateX ix s1 m, s1 ~ s2 ) => Foo ix s1 s2 m where