[英]Trouble with ST's type in a transformer stack
I am having some trouble dealing with the forall
quantifier in ST
's type. 我在处理
ST
类型的forall
量词时遇到一些麻烦。 The following (simplified) code sample works fine, producing the expected result. 下面的(简化的)代码示例可以正常工作,并产生预期的结果。
import Control.Monad
import Control.Monad.ST
return' :: a -> ST s a
return' = return
function :: a -> a
function x = runST $ do
-- Some complicated expression eventually producing a result
return' x
This is fine, if all I want to do is have ST
. 如果我想做的只是拥有
ST
,那就很好。 But in my computation, I want a state transformer computation that might also fail, so I attempt to add ExceptT
to the stack. 但是在我的计算中,我希望状态转换器的计算也可能会失败,因此我尝试将
ExceptT
添加到堆栈中。
import Control.Monad
import Control.Monad.ST
import Control.Monad.Except
return' :: a -> ExceptT String (ST s) a
return' = return
function :: a -> Either String a
function x = runST . runExceptT $ do
-- Some complicated expression that might fail
return' x
Unfortunately, I get a rather bizarre error message. 不幸的是,我收到了一个很奇怪的错误消息。
example.hs:9:14:
Couldn't match type `ST s0 (Either String a)'
with `forall s. ST s (Either String a)'
Expected type: ST s0 (Either String a) -> Either String a
Actual type: (forall s. ST s (Either String a))
-> Either String a
Relevant bindings include
x :: a (bound at example.hs:9:10)
function :: a -> Either String a (bound at example.hs:9:1)
In the first argument of `(.)', namely `runST'
In the expression: runST . runExceptT
I have only a vague understanding of the rank-2 type used by ST
, so I'm not really sure how to approach this error. 我对
ST
所使用的rank-2类型只有一个模糊的了解,因此我不确定如何解决此错误。 How can I safely put ST
at the bottom of a monad transformer stack without getting problems with the forall
? 我怎么能放心地把
ST
在单子转换堆的底部没有得到问题与forall
?
(For those curious, I'm using ST
because I want my computation to use a mutable array and then freeze it at the end. That shouldn't be relevant to this problem, but this is why I can't simply use State
instead) (对于那些好奇的人,我使用
ST
是因为我希望我的计算使用可变数组,然后在最后冻结它。这与该问题无关,但这就是为什么我不能简单地使用State
来代替)
All you need to do is replace the .
您需要做的就是更换
.
behind runST
by $
, and then you can use ordinary return
instead of return'
as well. 在
$
后面的runST
后面,然后您也可以使用普通的return
来代替return'
。
import Control.Monad
import Control.Monad.ST
import Control.Monad.Except
function :: a -> Either String a
function x = runST $ runExceptT $ do
return x
main = return ()
(At least for me this compiles, without problems.) (至少对我而言,此编译没有问题。)
See this answer for the theory behind the error. 有关错误背后的理论,请参见此答案 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.