[Haskellcafe] class Ref...
David Menendez
zednenem at psualum.com
Sun Jun 12 18:04:34 EDT 2005
Sven Panne writes:
 ajb at spamcop.net wrote:
 > Quoting Gracjan Polak <gracjan at acchsh.com>:
 > [...]
 >>Is there any reason why isn't it included?
 >
 >
 > Nobody could agree on the details. For example, MVars are
 > perfectly respectable Refs on the IO monad. So would it make sense
 > to add an instance for that? If so, the functional dependency
 > should go, which introduces its own problems.

 A few more design problems:

 * Due to the functional dependency, that class is not Haskell98,
 which is a *very* good reason IMHO not to standardize it, at least
 in that way. Remember: There are not only GHC and Hugs out
 there...

 * The 3 operations should not be packed together in a single class,
 because there might be e.g. references which you can't create
 (e.g. OpenGL's state variables), references which are readonly >
 and even references which are writeonly.

 * What about strictness of e.g. the setter? There is no "right"
 version, this depends on the intended usage.

 * Are the references located in the monad (like in the suggested
 class) or are they within objects, which have to be given as
 additional arguments (e.g. like wxHaskell's widgets/Attr/Prop).

 * Atomic operations might be needed, too.
These are all good points, but while it's fair to say that a MonadRef
class is wrong for some situations, I don't think it's wrong for all
situations. It isn't Haskell98, but neither is the ST monad or
practically anything else in Control.Monad.*. Regarding strictness vs.
nonstrictness, I would say leave it up to the specific monad.
I think the best way to look at MonadRef is as a generalization of
MonadState.
Consider:
> {# OPTIONS fglasgowexts #}
>
> import Control.Monad.Reader
> import Control.Monad.State
> import Control.Monad.ST
> import Data.STRef
>
> class Monad m => MonadRef r m  m > r where
> newRef :: a > m (r a)
> readRef :: r a > m a
> writeRef :: r a > a > m ()
>
> instance MonadRef (STRef r) (ST r) where
> newRef = newSTRef
> readRef = readSTRef
> writeRef = writeSTRef
>
> instance MonadRef r m => MonadRef r (ReaderT e m) where
> newRef = lift . newRef
> readRef = lift . readRef
> writeRef = (lift.) . writeRef
>
>
>
> newtype RefToState r s m a = RTS (ReaderT (r s) m a)
> deriving (Functor, Monad)
>
> instance MonadRef r m => MonadState s (RefToState r s m) where
> get = RTS (ask >>= readRef)
> put s = RTS (ask >>= \r > writeRef r s)
>
> evalRefToState :: MonadRef r m => RefToState r s m a > s > m a
> evalRefToState (RTS m) s0 = newRef s0 >>= runReaderT m
>
> runRefToState :: MonadRef r m => RefToState r s m a > s > m (a, s)
> runRefToState (RTS m) s0 = do
> r < newRef s0
> x < runReaderT m r
> s < readRef r
> return (x,s)

David Menendez <zednenem at psualum.com>  "In this house, we obey the laws
<http://www.eyrie.org/~zednenem>  of thermodynamics!"
More information about the HaskellCafe
mailing list