我在随机函数中播放随机函数,该函数给出了一个随机值的无限列表,如“了解您对Haskell的好作品”第9章所示。该代码是这样的:Haskell错误:无法推断(随机a0)产生于
randoms' :: (RandomGen g, Random a) => g -> [a]
randoms' gen = let (value, newGen) = random gen
in value : randoms' newGen
为了记录随机生成,我改变randoms'
了一下以下几点:
randoms'' :: (RandomGen g, Random a) => g -> [(a, g)]
randoms'' gen = let (value, newGen) = random gen
in (value, newGen) : randoms'' newGen
它按预期工作。
然后我重写了它在列表理解的风格:
randoms''' :: (RandomGen g, Random a) => g -> [(a, g)]
randoms''' gen = random gen : [random gen' | (_, gen') <- randoms''' gen]
这一次,编译器给出了错误:从使用“随机量”“””所产生的无法推断(随机A0) ......类型变量 'A0' 是暧昧...
但是,如果我用的具体类型指定randoms'''
类型,例如,
randoms''' :: StdGen -> [(Int, StdGen)]
randoms''' gen = random gen : [random gen' | (_, gen') <- randoms''' gen]
它再次正常工作,并提供与randoms''
完全相同的结果。
我想知道为什么类型推断适用于randoms''
但是对于randoms'''
而言失败。谁能告诉我为什么这两个不相等,以及如何修复randoms'''
的代码?
此外,我尝试与具有相似结构的测试代码:
generate :: (Integral a, RealFrac b) => a -> (b,a)
generate m = let x = 1.2^^m in (x, ceiling x)
foo :: (Integral g, RealFrac a) => g -> [(a,g)]
foo gen = let (value, newGen) = generate gen
in (value, newGen) : foo newGen
foo' :: (Integral g, RealFrac a) => g -> [(a, g)]
foo' gen = generate gen : [generate gen' | (_, gen') <- foo' gen]
foo'' :: (Integral g, RealFrac a) => g -> [(a, g)]
foo'' gen = [generate gen' | gen' <- gen : map snd (foo'' gen)]
原来foo
,foo'
和foo''
一切工作的罚款。显然,它不是一个单态与多态的问题。这似乎是random
的特定问题。
您抛弃了由'randoms''''('(_,gen')< - ...')生成的实际值,因此编译器不知道在哪种类型上实例化使用'randoms'' “';没有理由选择相同类型的'a'作为输出,也没有其他特殊类型,所以它是不明确的。在单形的情况下,没有可能的实例 - 当然它可能只为递归情况选择“Int”。 – user2407038