2013-04-26 106 views
4

在Haskell,这个工程:理解为什么A/B不工作,但fromInteger A/fromInteger B则

ghci>5/2 
2.5 

大。但如果我分配5和2变量..

Main> let a = 5 
Main> let b = 2 
Main> a/b 
<interactive>:68:2: 
    No instance for (Fractional Integer) 
     arising from a use of `/' 
    Possible fix: add an instance declaration for (Fractional Integer) 
    In the expression: a/b 
    In an equation for `it': it = a/b 
Main> 

我得到错误了wazoo。我能解决的唯一方法是说:

*Main> fromInteger a/fromInteger b 
2.5 
*Main> 

fromInteger发生了什么事?为什么我需要它来完成这项工作?

回答

7
Prelude> :t 5/2   -- The type is inferred to be a fractional 
5/2 :: Fractional a => a 
Prelude> :t (/)    -- ...because the type of (/) 
(/) :: Fractional a => a -> a -> a 
Prelude> let x = 5 
Prelude> let y = 2 
Prelude> :t x    -- In GHC there are addditional type defaulting rules 
x :: Integer     -- Instead of Num a => a, a lone integral is typed as `Integer` 
Prelude> :t y 
y :: Integer 
Prelude> :i Fractional  -- Notice that 'Integer' is not an instance of 'Fractional' 
class Num a => Fractional a where 
    (/) :: a -> a -> a 
    recip :: a -> a 
    fromRational :: Rational -> a 
    -- Defined in `GHC.Real' 
instance Fractional Float -- Defined in `GHC.Float' 
instance Fractional Double -- Defined in `GHC.Float' 

简而言之? GHCi类型 - 默认您的允许变量为Integer,它没有Fractional实例(因为Integer s不是分数)。在通过ghc编译的Haskell程序中,类型将会统一起来。

编辑:我应该补充一点,我试图说明如何将let x = 4推断为Double在更大的背景下,而不是GHCi。为了回应哈马尔的回答,这不仅是单一性,还与违约类型有关。 ab可以单式为Double,如在GHC编译的函数中那样,但是由于单态限制和逐行类型推断的组合,我们无法获得x :: Num a => ax :: Double - 两者都适合您需要。

10

这是monomorphism restriction在工作。 ab的类型默认为Integer,显然不能与/一起使用,因为它只适用于Fractional类型。

您可以通过添加类型注释定义ab时解决这一问题:

> let a = 5 :: Double 
> let b = 2 :: Double 
> a/b 
2.5 

,或者您可以使用十进制文本将默认为Double

> let a = 5.0 
> let b = 2.0 
> a/b 
2.5 

这不会是一个问题如果这三行是类型检查在一起,因为他们将在编译模块,或者如果您已输入

let a = 5; b = 2 in a/b 

然而,当在GHCI单独类型的,它们是类型检查一次一个,所以违约,在评价let a = 5拾取Integer当施加因为在那个点上的a唯一的限制是Num。它不知道我们需要的Fractional约束,以便稍后使用/

2

正如其他人所指出的,这是Monomorphism Restriction的错。相反注释所有的类型,如(a :: Double)/(b :: Double)的,我觉得很容易,只需将其关闭:

Prelude> :set -XNoMonomorphismRestriction 
Prelude> let a = 5 
Prelude> let b = 2 
Prelude> a/b 
2.5 

(您可以保存:set行动在.ghci file,所以你不需要每次写)

+0

你从哪里找到'-XNoMonomorphismRestriction',我在哪里可以找到更多像这样的东西,还有其他问题? – CodyBugstein 2013-04-28 20:44:03

+0

@Imray:GHC用户指南很长很密集,但充满了这样的有用工具。尝试http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html。 Haskell wiki也有很多很棒的信息,但它更加分散。 – amindfv 2013-04-29 05:16:09

相关问题