Oh, sweet beans. I hadn't planned to incorporate mutable references -- my code uses them highly infrequently -- but I suppose that since mutable references are really equivalent to single-threadedness where referential transparency is concerned, that could be pulled off -- I would still want a StateThread associated type, but that'd just be RealWorld for IO and STM, I guess.<br>
<br clear="all">Louis Wasserman<br><a href="mailto:wasserman.louis@gmail.com">wasserman.louis@gmail.com</a><br>
<br><br><div class="gmail_quote">On Thu, Feb 19, 2009 at 2:40 PM, Ryan Ingram <span dir="ltr"><<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
So, why not use this definition? Is there something special about ST<br>
you are trying to preserve?<br>
<br>
-- minimal complete definition:<br>
-- Ref, newRef, and either modifyRef or both readRef and writeRef.<br>
class Monad m => MonadRef m where<br>
type Ref m :: * -> *<br>
newRef :: a -> m (Ref m a)<br>
readRef :: Ref m a -> m a<br>
writeRef :: Ref m a -> a -> m ()<br>
modifyRef :: Ref m a -> (a -> a) -> m a -- returns old value<br>
<br>
readRef r = modifyRef r id<br>
writeRef r a = modifyRef r (const a) >> return ()<br>
modifyRef r f = do<br>
a <- readRef r<br>
writeRef r (f a)<br>
return a<br>
<br>
instance MonadRef (ST s) where<br>
type Ref (ST s) = STRef s<br>
newRef = newSTRef<br>
readRef = readSTRef<br>
writeRef = writeSTRef<br>
<br>
instance MonadRef IO where<br>
type Ref IO = IORef<br>
newRef = newIORef<br>
readRef = readIORef<br>
writeRef = writeIORef<br>
<br>
instance MonadRef STM where<br>
type Ref STM = TVar<br>
newRef = newTVar<br>
readRef = readTVar<br>
writeRef = writeTVar<br>
<br>
Then you get to lift all of the above into a monad transformer stack, MTL-style:<br>
<br>
instance MonadRef m => MonadRef (StateT s m) where<br>
type Ref (StateT s m) = Ref m<br>
newRef = lift . newRef<br>
readRef = lift . readRef<br>
writeRef r = lift . writeRef r<br>
<br>
and so on, and the mention of the state thread type in your code is<br>
just gone, hidden inside Ref m. It's still there in the type of the<br>
monad; you can't avoid that:<br>
<br>
newtype MyMonad s a = MyMonad { runMyMonad :: StateT Int (ST s) a }<br>
deriving (Monad, MonadState, MonadRef)<br>
<br>
But code that relies on MonadRef runs just as happily in STM, or IO,<br>
as it does in ST.<br>
<br>
-- ryan<br>
<br>
2009/2/19 Louis Wasserman <<a href="mailto:wasserman.louis@gmail.com">wasserman.louis@gmail.com</a>>:<br>
<div><div></div><div class="Wj3C7c">> It does. In the most recent version, the full class declaration runs<br>
><br>
> class MonadST m where<br>
> type StateThread m<br>
> liftST :: ST (StateThread m) a -> m a<br>
><br>
> and the StateThread propagates accordingly.<br>
><br>
> Louis Wasserman<br>
> <a href="mailto:wasserman.louis@gmail.com">wasserman.louis@gmail.com</a><br>
><br>
><br>
> On Thu, Feb 19, 2009 at 2:10 AM, Sittampalam, Ganesh<br>
> <<a href="mailto:ganesh.sittampalam@credit-suisse.com">ganesh.sittampalam@credit-suisse.com</a>> wrote:<br>
>><br>
>> Henning Thielemann wrote:<br>
>> > On Mon, 16 Feb 2009, Louis Wasserman wrote:<br>
>> ><br>
>> >> Overnight I had the following thought, which I think could work<br>
>> >> rather well. The most basic implementation of the idea is as<br>
>> >> follows:<br>
>> >><br>
>> >> class MonadST s m | m -> s where<br>
>> >> liftST :: ST s a -> m a<br>
>> >><br>
>> >> instance MonadST s (ST s) where ...<br>
>> >> instance MonadST s m => MonadST ...<br>
>> ><br>
>> > Like MonadIO, isn't it?<br>
>><br>
>> I think it should be, except that you need to track 's' somewhere.<br>
>><br>
>> Ganesh<br>
>><br>
>><br>
>> ==============================================================================<br>
>> Please access the attached hyperlink for an important electronic<br>
>> communications disclaimer:<br>
>><br>
>> <a href="http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html" target="_blank">http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html</a><br>
>><br>
>> ==============================================================================<br>
>><br>
><br>
><br>
</div></div><div><div></div><div class="Wj3C7c">> _______________________________________________<br>
> Haskell-Cafe mailing list<br>
> <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
> <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
><br>
><br>
</div></div></blockquote></div><br>