haskell - Haskell 中编译后的代码和 ghci 的区别
问题描述
我有以下代码:
-- 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)
当我将 myrandomFoobar
函数直接输入 ghci 时,它工作正常。
我对 Haskell 很陌生,对此完全感到困惑——有人知道这里发生了什么吗?为什么 ghci 与这里的编译器不同?
解决方案
GHCi 默认启用 ExtendedDefaultRules 扩展,这会导致为一些不明确的类型选择默认类型,而不是仅仅抛出错误。为了让你的代码在任何地方都能工作,最好的解决方案是添加一个类型注释,使类型明确。这种情况下的歧义在于数字文字是多态的。5.5
可能是 a Float
、 a Double
、 aRational
等。由于最后你只得到 a Bool
,类型推断无法确定你想要哪个,因为任何一个都是有效的。使用(5.5 :: Double)
而不是仅仅5.5
会这样做,假设Double
是你想要的类型。
推荐阅读
- mysql - 尽管为其他表工作,但 MySQL 中键“PRIMARY”的重复条目
- go - 在测试执行期间如何干预 GO 自动化测试?
- php - 即使从 CDN 使用 select2 功能也不起作用
- reactjs - 开玩笑地模拟动画完成回调
- php - json数组到json php
- ruby-on-rails - 运行 rspec 时如何从命令行设置常量
- google-bigquery - Dataflow Runner - 尝试刷新以获取初始 access_token
- node.js - 哪个 ORM 最适合 nodejs?
- c++ - 将用户输入作为包含通配符表达式的字符串变量
- html - 输入类型(HTML)中的值和数据值有什么区别