简体   繁体   English

变压器堆栈中的ST型故障

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM