我有一个类似下面的测试函数,它使用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
如果我取消注释类型签名go :: Int -> ST s Int
:
Couldn't match type `s1' with `s'
`s1' is a rigid type variable bound by
the type signature for go :: Int -> ST s1 Int at A.hs:12:16
`s' is a rigid type variable bound by
a type expected by the context: ST s Int at A.hs:10:10
Expected type: Gen (PrimState (ST s1))
Actual type: Gen s
In the second argument of `uniformR', namely `gen'
In a stmt of a 'do' block: v <- uniformR (1, x) gen
In the expression:
do { v <- uniformR (1, x) gen;
return v }
答案 0 :(得分:7)
麻烦的是,当你说
时gen <- ... :: (forall s. ST s (Gen (PrimState (ST s))))
s
现在已修复到s
runST
提供的任何内容 - 即我们无法将其视为类型变量,因为您的签名会让您相信[1] ]。当编译器说&#34;刚性类型变量&#34;时,这就是它的含义。为了强调它是固定的,让我们将其称为S1
以获得此答案。
请注意
let go :: Int -> ST s Int
相当于
let go :: forall s. Int -> ST s Int
即,go
必须适用于任何 s
。但是你说了
v <- uniformR (1,x) gen
尝试绑定类型ST S1 <something>
的计算。 go
应该与任何 s
一起使用,而不仅仅是S1
,所以这是一个错误。 go
的正确签名是Int -> ST S1 Int
,但我们当然只是为了论证而编造S1
,并且真正的S1
在源代码中没有名称文件,因此go
无法给出签名,即使它的类型很好。
[1]哦,你已经ScopedTypeVariables
了,所以看起来forall
就在那里,因为你正在尝试范围s
。这不起作用 - 范围变量仅适用于forall
的函数体。您可以通过将签名移到<-
:
(gen :: Gen (PrimState (ST s))) <- initialize ...
之后s
将被正确确定范围。
答案 1 :(得分:1)
不是一个完整的答案,但我可以通过传递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