Haskell中编译代码与GHCi的区别

3

我有如下代码:

-- defined externally in a module that compiles just fine
-- normal :: (RandomGen g, Random r, Floating r, Ord r) => r -> r -> g -> (r, g)
-- poisson :: (RandomGen g, Random r, Floating r, Ord r) => r -> g -> (Integer, g)
-- binomial :: (RandomGen g, Random r, Floating r, Ord r) => r -> g -> (Bool, g)
data Foobar = Foobar { n :: Double, p :: Integer, b :: Bool } deriving (Show)

randomFoobar :: (RandomGen g) => g -> (Foobar, g)
randomFoobar g0 = let (n, g1) = normal 10.0 1.0 g0
                      (p, g2) = poisson 5.5 g1
                      (b, g3) = binomial 0.5 g2
                  in (Foobar n p b, g3)

当我尝试编译这段代码时,出现了一系列错误,其中第一个是:
Foobar.hs:8:33: error:
    • Could not deduce (Random r0) arising from a use of ‘poisson’
      from the context: RandomGen g
        bound by the type signature for:
                   randomFoobar :: forall g. RandomGen g => g -> (Foobar, g)
        at Foobar.hs:6:1-49
      The type variable ‘r0’ is ambiguous
      These potential instances exist:
        instance Random Integer -- Defined in ‘System.Random’
        instance Random Bool -- Defined in ‘System.Random’
        instance Random Char -- Defined in ‘System.Random’
        ...plus four others
        ...plus 29 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: poisson 5.5 g1
      In a pattern binding: (p, g2) = poisson 5.5 g1
      In the expression:
        let
          (n, g1) = normal 10.0 1.0 g0
          (p, g2) = poisson 5.5 g1
          (b, g3) = binomial 0.5 g2
        in (Foobar n p b, g3)

当我在ghci中直接输入randomFoobar函数时,它可以正常工作。
我对Haskell非常陌生,并被这个问题搞得一脸懵逼 - 有人知道这里发生了什么吗?为什么ghci和编译器不一样?
1个回答

6

GHCi默认启用ExtendedDefaultRules扩展,这会导致在某些不明确的类型中选择默认类型而不是仅抛出错误。为了使您的代码在任何地方都能正常工作,最好的解决方案是添加一个类型注释,使该类型变得明确无误。在这种情况下的歧义是数值字面量的多态性。例如,5.5 可以是FloatDoubleRational等等。由于最后您只获取一个Bool值,类型推断无法确定您想要哪个类型,因为任何一种类型都是有效的。使用(5.5 :: Double)代替只使用5.5将解决此问题,假设Double是您需要的类型。


非常感谢,我已经为此烦恼了一整天了! :-) - Nathan Kronenfeld

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接