I see lots of examples of ST monad in the context of do
notation; however since that's not suitable to my purpose, I try to use ST monad for instance newSTRef
and modifySTRef
outside of do
thread.
The type is automatically added by HLS of VSCode.
ref :: ST s (STRef s Integer)
ref = newSTRef (1)
x :: ST s ()
x = modifySTRef ref 2
error: ref
in the last line
Couldn't match expected type ‘STRef s a0’
with actual type ‘ST s0 (STRef s0 Integer)’
Well, sure I can see the error saying the type doesn't match, but I don't know how to fix it.
What is the proper usage of ST Monad outside of do
?
EDIT:
My purpose without do
is
like the one mentioned,
do
is merely a syntax sugar and often I'd like to avoid it in order to write a code in more straightforward functional way.The purpose to obtain the mutable object is to develop FRP, and the sequential definition and updates of
ref
in the singledo
thread is not useful for the purpose.
CodePudding user response:
The problem here is that modifySTRef
takes an STRef s a
, not a ST s (STRef s a)
. ST
was designed to utilize monad properties to secure mutable operations from being abused, so all modifications can happen only in an ST
context. Therefore, you need to use the powers of the context to extract the pure STRef
reference.
Normally you would do
it like this:
x :: ST s ()
x = do
refv <- ref
modifySTRef refv 2
But since you would like to avoid this sugar, you can do right what it desugars to:
x :: ST s ()
x = refv >>= \refv -> modifySTRef refv 2
You can read more about the do
notation and how it is resolved here