为什么这两个haskell功能不相同?

Mik*_*H-R 3 haskell

我一直在看这些功能:

import Data.Digits (digits)
numberDivider (a,b) = a / b
numberDivider2 (num,denom) = num / denom
                              where
                                a = head $ digits 10 num
                                b = head . tail $ digits 10 denom
Run Code Online (Sandbox Code Playgroud)

我们可以看看这些函数的类型:

?> :t numberDivider2
numberDivider2 :: (Integral a, Fractional a) => (a, a) -> a
?> :t numberDivider
numberDivider :: Fractional a => (a, a) -> a
Run Code Online (Sandbox Code Playgroud)

numberDivider会做你认为它做的事情.numberDivider2得到:

No instance for (Show a0) arising from a use of ‘print’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
  instance Show Double -- Defined in ‘GHC.Float’
  instance Show Float -- Defined in ‘GHC.Float’
  instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
    -- Defined in ‘GHC.Real’
  ...plus 34 others
In a stmt of an interactive GHCi command: print it
Run Code Online (Sandbox Code Playgroud)

用正确的参数调用时(例如(48,98)).现在我不知道如何制作更具体的东西会导致歧义?我觉得我在某种程度上是愚蠢的.(我也不明白为什么函数需要从(a,a) -> a我认为它将是(a,a) -> ba Integral和b是浮点或其他东西.

我已经尝试输入类型注释来强制它使用Float来获得结果.

有人能指出我在这里缺少的东西吗?

bhe*_*ilr 6

这很可能来自于digits我的猜测,我猜这个定义是其中的Integrala => a一个论点.然后,这将附加约束Integral放在参数上numberDivider2.事实证明,没有一个类型,它是两者的一个实例FractionalIntegral.但是,当您输入数字文字时,它会尝试转换Num a => a(Integral a, Fractional a) => a,并且在GHCi中有一些特殊规则可以尝试查找也使用的实例,Show以便您可以将其打印到屏幕上.由于不存在此类型,因此会出现错误.

现在,真正的问题似乎是由于对Haskell数字系统的误解.您不能/在所有数字上使用,例如Ints,因为/没有为这些类型定义.您只能使用/小数类型,因此Fractional类型类.如果要将Ints或Integers 转换为FloatDouble执行浮点除法,可以使用fromIntegral它们将它们转换为任何Num类型,例如

a = head $ digits 10 $ fromIntegral num
b = head . tail $ digits 10 $ fromIntegral denom
Run Code Online (Sandbox Code Playgroud)

这应该Integral从函数中删除约束.


在查看类型后digits,我发现这不起作用.相反,你可能想要类似的东西

numberDivider2 :: (Integral a, Fractional b) => (a, a) -> b
numberDivider2 (num, denom) = fromIntegral num / fromIntegral denom
    where
        a = head $ digits 10 num
        b = head . tail $ digits 10 denom
Run Code Online (Sandbox Code Playgroud)

请注意fromIntegrals 的位置,它们会Integral在您要执行Fractional操作的位置转换每个值.

  • ;)...但是Haskell的Jon Skeet是不是它的东西? (2认同)