变压器组中 ST 类型的问题
Trouble with ST's type in a transformer stack
我在处理 ST
类型中的 forall
量词时遇到了一些问题。以下(简化的)代码示例工作正常,产生了预期的结果。
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
这很好,如果我只想拥有 ST
。但是在我的计算中,我想要一个可能也会失败的状态转换器计算,所以我尝试将 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
不幸的是,我收到一条相当奇怪的错误消息。
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
我对 ST
使用的 rank-2 类型只有一个模糊的理解,所以我不太确定如何处理这个错误。我怎样才能安全地将 ST
放在 monad 转换器堆栈的底部而不会出现 forall
的问题?
(对于那些好奇的人,我使用 ST
因为我希望我的计算使用可变数组然后在最后冻结它。这不应该与这个问题相关,但这是为什么我不能简单地使用 State
来代替)
只需要将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 ()
(至少对我来说这个编译没有问题。)
有关错误背后的理论,请参阅 this answer。
我在处理 ST
类型中的 forall
量词时遇到了一些问题。以下(简化的)代码示例工作正常,产生了预期的结果。
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
这很好,如果我只想拥有 ST
。但是在我的计算中,我想要一个可能也会失败的状态转换器计算,所以我尝试将 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
不幸的是,我收到一条相当奇怪的错误消息。
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
我对 ST
使用的 rank-2 类型只有一个模糊的理解,所以我不太确定如何处理这个错误。我怎样才能安全地将 ST
放在 monad 转换器堆栈的底部而不会出现 forall
的问题?
(对于那些好奇的人,我使用 ST
因为我希望我的计算使用可变数组然后在最后冻结它。这不应该与这个问题相关,但这是为什么我不能简单地使用 State
来代替)
只需要将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 ()
(至少对我来说这个编译没有问题。)
有关错误背后的理论,请参阅 this answer。