type ST s a = ST (s -> (s, a))
runST :: (forall s. ST s a) -> a
runST (ST f) = case (f realWorld) of (_, a) -> a
If you look closely, there are many errors, but the overall structure of runST
is as above.
So, if you want to apply runST
to a value of type ST s a
, which is identical to s -> (s, a)
, its type s
must be fully parameterized.
Some kinds of functions depending on concrete type can't applied by runST
.
Example of inappropriate function is below.
\s -> (s + s, "hello world") // this won't run cause it depends on (Num) type class.
fun [] = ([], 0)
fun (x : xs) = (xs, length (x : xs)) // this won't run. It depends on ([]) type.
So, functions to be executed by runST should be as follows.
\s -> (s, fun s)
fun = maybe some native code, not haskell.
The point is that s
from (s, a)
term of s -> (s, a)
should always same as s
itself, like an identity.
We call it parametricity.
Currently I know that if s
has RealWorld
in it, even what seems to be an id
can make meaningful calculations. (Although it's not pure Haskell).
To prove what I guessed, I prepared the following experiment.
//given
newMutVar# :: v -> State# s -> (# State# s, MutVar# s v #)
//then (this is pseudo code)
let (# s#, var# #) = newMutVar# "hello world" (State# 0) in
s# == State# 0
and see if the result is True
, which implies that newMutVar#
acts like id
for State#
.
But I can't do this because I don't know how to generate State# s
value. I know how to do it only for RealWorld
, and its meaningless cause RealWorld
only has one value inside so it always be identical no matter what the mapping is.
Also, even if I succeed generating State# 0
, there's no way to compare State# 0
to s#
, cause State# s
doesn't implement Eq
.