我一直在研究这些功能:
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
我们可以看一下这些函数的类型:
λ> :t numberDivider2
numberDivider2 :: (Integral a, Fractional a) => (a, a) -> a
λ> :t numberDivider
numberDivider :: Fractional a => (a, a) -> a
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
用正确的参数调用时(例如(48,98))。现在我不知道如何制作更具体的东西会导致模糊不清?我觉得我在某种程度上是愚蠢的。 (我也不知道为什么函数需要从(a,a) -> a
开始,因为我认为它是(a,a) -> b
,其中a是Integral
而b是浮点数等等。 / p>
我尝试过输入类型注释来强制它使用Float来获得结果。
有人可以指出我在这里失踪的东西吗?
答案 0 :(得分:6)
这可能来自digits
的定义,我猜测它将Integrala => a
作为其参数之一。然后,将Integral
的附加约束放在numberDivider2
的参数上。事实证明,没有一种类型是Fractional
和Integral
的实例。但是,当您输入数字文字时,它会尝试从Num a => a
转换为(Integral a, Fractional a) => a
,而在GHCi中,有一些特殊规则可以尝试查找也使用Show
的实例,以便您可以将其打印到屏幕上。由于不存在此类型,因此会出现错误。
现在,真正的问题似乎是由于对Haskell号码系统的误解。您无法对所有号码使用/
,例如Int
,因为/
未针对这些类型定义。您只能对小数类型使用/
,因此Fractional
类型类。如果您想将Int
或Integer
转换为Float
或Double
以执行浮点除法,可以使用fromIntegral
将它们转换为任意值Num
类型,例如
a = head $ digits 10 $ fromIntegral num
b = head . tail $ digits 10 $ fromIntegral denom
这应该从函数中删除 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
请注意fromIntegral
的位置,它们会在您要执行Integral
操作的位置转换每个Fractional
值。
答案 1 :(得分:4)
现在我不知道如何制作更具体的内容会导致模糊不清?
在这两种情况下都不明确,但在numberDivider
的情况下,可以使用Haskell的默认规则解决歧义。在此特定实例中,这些规则基本上表示如果可能有多种数字类型且其中一种是Integer
,请选择Integer
。如果无法Integer
,但Double
是,请选择Double
。如果两者都不可能,那么模糊性仍然存在。
如果numberDivider
Integer
不可能,因为Integer
不是Fractional
的实例,而Double
是Double
。因此,numberDivider
被选中。
如果Integral
也不可能,因为根本没有Fractional
和Fractional
的类型。因此,模棱两可仍然存在。
你可能会争辩说,一组正好0种可能的类型不是模糊的,但根本不可能,所以错误信息应该是不同的,但它也必须考虑可能在别处定义的实例。也就是说,虽然标准库中没有Integral
和{{1}}的任何类型,但它们可能会在其他地方定义,因此我们无法排除这种可能性(甚至虽然没有意义)。