2020-05-18 15:59:07 +03:00
|
|
|
module Data.IORef
|
|
|
|
|
|
|
|
-- Implemented externally
|
|
|
|
-- e.g., in Scheme, passed around as a box
|
|
|
|
data Mut : Type -> Type where [external]
|
|
|
|
|
|
|
|
%extern prim__newIORef : forall a . a -> (1 x : %World) -> IORes (Mut a)
|
|
|
|
%extern prim__readIORef : forall a . Mut a -> (1 x : %World) -> IORes a
|
|
|
|
%extern prim__writeIORef : forall a . Mut a -> (1 val : a) -> (1 x : %World) -> IORes ()
|
|
|
|
|
|
|
|
export
|
|
|
|
data IORef : Type -> Type where
|
|
|
|
MkRef : Mut a -> IORef a
|
|
|
|
|
|
|
|
export
|
Back to HasIO, remove MonadIO
Following a fairly detailed discussion on slack, the feeling is
generally that it's better to have a single interface. While precision
is nice, it doesn't appear to buy us anything here. If that turns out to
be wrong, or limiting somehow, we can revisit it later. Also:
- it's easier for backend authors if the type of IO operations is
slightly less restrictive. For example, if it's in HasIO, that limits
alternative implementations, which might be awkward for some
alternative back ends.
- it's one less extra detail to learn. This is minor, but there needs to
be a clear advantage if there's more detail to learn.
- It is difficult to think of an underlying type that can't have a Monad
instance (I have personally never encountered one - if they turns out
to exist, again, we can revisit!)
2020-06-21 21:21:22 +03:00
|
|
|
newIORef : HasIO io => a -> io (IORef a)
|
2020-05-18 15:59:07 +03:00
|
|
|
newIORef val
|
|
|
|
= do m <- primIO (prim__newIORef val)
|
|
|
|
pure (MkRef m)
|
|
|
|
|
2020-05-29 18:39:11 +03:00
|
|
|
%inline
|
2020-05-18 15:59:07 +03:00
|
|
|
export
|
2020-06-21 03:18:43 +03:00
|
|
|
readIORef : HasIO io => IORef a -> io a
|
2020-05-18 15:59:07 +03:00
|
|
|
readIORef (MkRef m) = primIO (prim__readIORef m)
|
|
|
|
|
2020-05-29 18:39:11 +03:00
|
|
|
%inline
|
2020-05-18 15:59:07 +03:00
|
|
|
export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
writeIORef : HasIO io => IORef a -> (val : a) -> io ()
|
2020-05-18 15:59:07 +03:00
|
|
|
writeIORef (MkRef m) val = primIO (prim__writeIORef m val)
|
|
|
|
|
2021-01-11 14:24:43 +03:00
|
|
|
%inline
|
|
|
|
export
|
|
|
|
writeIORef1 : HasLinearIO io => IORef a -> (1 val : a) -> io ()
|
|
|
|
writeIORef1 (MkRef m) val = primIO1 (prim__writeIORef m val)
|
|
|
|
|
2020-05-18 15:59:07 +03:00
|
|
|
export
|
Back to HasIO, remove MonadIO
Following a fairly detailed discussion on slack, the feeling is
generally that it's better to have a single interface. While precision
is nice, it doesn't appear to buy us anything here. If that turns out to
be wrong, or limiting somehow, we can revisit it later. Also:
- it's easier for backend authors if the type of IO operations is
slightly less restrictive. For example, if it's in HasIO, that limits
alternative implementations, which might be awkward for some
alternative back ends.
- it's one less extra detail to learn. This is minor, but there needs to
be a clear advantage if there's more detail to learn.
- It is difficult to think of an underlying type that can't have a Monad
instance (I have personally never encountered one - if they turns out
to exist, again, we can revisit!)
2020-06-21 21:21:22 +03:00
|
|
|
modifyIORef : HasIO io => IORef a -> (a -> a) -> io ()
|
2020-05-18 15:59:07 +03:00
|
|
|
modifyIORef ref f
|
|
|
|
= do val <- readIORef ref
|
|
|
|
writeIORef ref (f val)
|