我正在修改以下代码作为作业的一部分:
rand :: Random a => State StdGen a
rand = do
gen <- get
let (x, gen') = random gen
put gen'
return x
我被要求编写一个函数randR
,它完成与rand
函数相同的任务,但允许指定范围。所需类型为Random a => (a, a) -> State StdGen a
。我写了以下代码:
randR :: Random a => (a, a) -> State StdGen b
randR (lo, hi) = do
gen <- get
let (x, gen') = randomR (lo, hi) gen
put gen'
return x
这看起来是正确的;它几乎与模型完全一样。但是我收到以下错误:
Could not deduce (a ~ b)
from the context (Random a)
bound by the type signature for
randR :: Random a => (a, a) -> State StdGen b
(a ~ b)
是什么意思,以及为什么编译器可以推断&#34;推论&#34;它来自&#34;上下文&#34;?
答案 0 :(得分:7)
错误消息表明randR
:randR :: Random a => (a, a) -> State StdGen b
的签名中存在拼写错误。它应该是... -> RandState a
。
该消息粗略地表明编译器知道a
和b
需要是相同的类型,但它无法证明是这种情况。 a ~ b
是"equality constraint";将~
视为粗略含义=
。
关于上下文的部分只是编译器告诉你做什么知道类型约束的方式。在这种情况下,它几乎完全没有用,但经常你会看到像Could not deduce (Floating a) from the context (Num a)
这样的东西,或者其他一些直接的迹象表明函数需要一个额外的约束。
顺便说一句,通过添加GHC要求的约束,可以通过某些扩展 解决此问题:randR :: (Random a, a ~ b) => (a, a) -> State StdGen b
应该可以正常工作。 (我想。)为了你的目的,不要担心这个......