Reputation: 23135
I can write something like this:
import Control.Monad.ST (runST)
x :: (Monad m) => m a
x = undefined
f = runST x
And this will happily compile without a signature for f
.
So I've tried something similar:
g :: (Monad m) => m a -> m a
g = undefined
h x = runST (g x)
Yet this doesn't compile without a signature. Which I don't mind too much, as runST
is a rank-2 type, but I can't work out what signature to write for h
.
(Background)
This is a simplified example of real code I'm writing. Firstly I've got a function that works in MonadRef (e.g. ST or IO). It does a lot of manipulation on vectors. I'm creating a pure wrapper to this, but one needs to pass in the initial mutable vector, and it will produce a pure vector. Unlike the more general first mentioned function, the pure wrapper only works in ST.
Upvotes: 0
Views: 92
Reputation: 11963
The type signature that you're looking for is:
{-# LANGUAGE RankNTypes #-}
module Test where
import Control.Monad.ST
g :: (Monad m) => m a -> m a
g = undefined
h :: (forall s. ST s a) -> a
h x = runST (g x)
The (forall s. ST s a)
ensures that x
cannot decide what s
will be and so x
has to work for all s
, so it cannot leak out STRef
or similar out of the ST
computation.
Upvotes: 5