Haskell 在runST函数中传递作用域状态

Haskell 在runST函数中传递作用域状态,haskell,st,Haskell,St,我有一个如下所示的测试函数,它使用runST对状态进行内部变异。我在其中定义了另一个函数go,它返回Int作为结果包装在ST中(只是玩一些ST概念)。问题是我的函数类型签名似乎是错误的。如果我注释掉函数类型签名,代码运行良好。对于注释代码中的类型签名,它不会编译,因为编译器将go函数的状态解释为与封闭范围中的状态不同。我将非常感谢关于如何定义函数类型签名以将外部ST s传递到go函数的指针 {-# LANGUAGE ScopedTypeVariables #-} module Main wher

我有一个如下所示的测试函数,它使用
runST
对状态进行内部变异。我在其中定义了另一个函数
go
,它返回
Int
作为结果包装在
ST
中(只是玩一些
ST
概念)。问题是我的函数类型签名似乎是错误的。如果我注释掉函数类型签名,代码运行良好。对于注释代码中的类型签名,它不会编译,因为编译器将
go
函数的状态解释为与封闭范围中的状态不同。我将非常感谢关于如何定义函数类型签名以将外部
ST s
传递到
go
函数的指针

{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Data.Word(Word32)
import Data.Vector.Unboxed as U hiding (mapM_,create)
import Control.Monad.ST as ST
import Control.Monad.Primitive (PrimState)
import System.Random.MWC

test :: Word32 -> Int
test x = runST $ do
     gen <- initialize (U.singleton $ fromIntegral x :: U.Vector Word32) :: (forall s. ST s (Gen (PrimState (ST s))))
     let --go :: Int -> ST s Int
         go x = do
            v <- uniformR (1,x) gen
            return v
     i <- go 100
     return i

这不是一个完整的答案,但我也可以通过传递
gen

test :: Word32 -> Int
test x = runST $ do
     gen <- initialize (U.singleton $ fromIntegral x :: U.Vector Word32) :: (forall s. ST s (Gen (PrimState (ST s))))
     let go3 ::  (Num b, Variate b) => Gen (PrimState (ST s)) -> b -> ST s b
         go3 g x' = uniformR (1,x') g
     go3 gen 100
test::Word32->Int
测试x=runST$do
gen gen(原始状态(ST s))->b->ST s b
go3 g x'=uniformR(1,x')g
go3 gen 100

问题是当你说

gen <- ... :: (forall s. ST s (Gen (PrimState (ST s))))
v <- uniformR (1,x) gen
相当于

let go :: forall s. Int -> ST s Int
i、 例如,
go
必须适用于任何
s
。但是你说

gen <- ... :: (forall s. ST s (Gen (PrimState (ST s))))
v <- uniformR (1,x) gen

在这之后,
s
将被正确地确定范围。

是的,这显然是缺少范围的解决办法……我以前做过,并且想避免它。因此,这个问题。按照您的建议移动类型定义,可以解决这个问题。不过,我不清楚为何要这样做。所以,暂时不要打开它。@Sal,这是因为ScopedTypeVariables是如何工作的。您可以使用
::forall s..绑定类型变量
或在lambda绑定中,例如
\(x::[a])->{-a在这里绑定-}
。一元结合脱糖与lambda结合。
(gen :: Gen (PrimState (ST s))) <- initialize ...