purescript / purescript-st

The ST effect, for safe local mutation
BSD 3-Clause "New" or "Revised" License
25 stars 25 forks source link

Global region, take two #19

Closed rightfold closed 4 years ago

rightfold commented 6 years ago

Previous issue was #7, but that was still about effect rows.

Now that we no longer use effect rows, it is no longer possible to use ST globally by adding st :: ST a to the effect row of main.

I think that we can abstract over Effect and ST so that code that uses mutation can be used on both global and local state, as follows.

foreign import data Global :: Region

effectToST :: Effect ~> ST Global
stToEffect :: ST Global ~> Effect

instance MonadEffect (ST Global) where
  liftEffect = effectToST

Now we can abstract over it.

class MonadST s m | m -> s where
  liftST :: ST s ~> m

instance monadSTEffect :: MonadST Global Effect where
  liftST = stToEffect

instance monadSTST :: MonadST s ST where
  liftST = id

Now, STRef and Ref can be unified, allowing for code reuse. Similar for STArray and something I don't think exists yet (useful for fixing https://github.com/purescript-node/purescript-node-process/issues/8).

foreign import data Ref :: Region -> Type -> Type

newRef :: forall s m a. MonadST s m => a -> m (Ref s a)
readRef :: forall s m a. MonadST s m => Ref s a -> m a
writeRef :: forall s m a. MonadST s m => Ref s a -> a -> m Unit

Additionally, ST can be used without explicit lifting with monad transformers.

garyb commented 6 years ago

Moving everything to use MonadST constraints would destroy the ability to optimize ST I think (not that it is optimized in the 0.12 RC just now).

Honest question: why/when would you want to do this? I can't think of any situations where I've wanted a non-closed ST.

rightfold commented 6 years ago

When you have a library that already uses ST, but you want to use it from Effect (for example STArray; I've been using MVector lately in Haskell in both IO and ST, for production and testing respectively).

Granted, explicit liftST is enough for that, you don't need the constraint for all the operations (it would just be more convenient).

eric-corumdigital commented 5 years ago

Am wanting to use STObject in Effect. Got my upvote.