我有以下代码(yyyy
和mm
定义为Int
类型):
partOne = truncate ((fromIntegral yyyy + fromIntegral mm/100) * 1.25 + 0.97)
加载到GHCi中会给我一个错误:
No instance for (Integral Float) arising from a use of ‘truncate’
但是,如果我在GHCi中直接使用以下行,它可以正常工作:
truncate ((fromIntegral 2000 + fromIntegral 04/100) * 1.25 + 0.97)
似乎存在与Int
类型相关的问题,但我无法弄清楚如何。
另外,实际上我并不完全理解(Integral Float)
在这里的含义。
为了完整起见,这里包含了整个函数的定义,以防错误是由整个事件而不是单个语句引起的:
dowNumber :: Mnemonic -> PhonePad -> Date -> Float
dowNumber mn p (yyyy, mm, dd) = (partOne + partTwo) / 7 where
partOne = (truncate ((fromIntegral yyyy + (fromIntegral mm)/100) * 1.25 + 0.97))
partTwo = fromIntegral ((monthToPhone mn p mm) + dd)
Mnemonic
只是String
而PhonePad
是[(Char, Int)]
。 Date
为(Int, Int, Int)
。
答案 0 :(得分:3)
好吧,truncate
的类型为(RealFrac a, Integral b) => a -> b
,这意味着其多态结果需要满足Integral
约束。但是,dowNumber
的类型表示(partOne + partTwo) / 7
是Float
。因此,partOne
和partTwo
也需要Float
s。
如果Float
是某种整数类型,那么这是可能的。但事实并非如此。但是为了从Integral
获得一个浮动,所有缺失的是fromIntegral
的另一个partOne
:
partOne = fromIntegral $ truncate $ …
或在您尝试划分之前:
dowNumber … = fromIntegral (partOne + partTwo) / 7 where
…
注释类型。在这个特定情况下,GHC抱怨truncate
,因此约partOne
。让我们简化你的例子一分钟:
number :: Float
number = (a + b) / 2 where
a = truncate $ fromIntegral 5 / 2
b = fromIntegral $ 12
这会产生与之前程序相同的错误:
SO.hs:3:7: No instance for (Integral Float) arising from a use of ‘truncate’ In the expression: truncate In the expression: truncate $ fromIntegral 5 / 2 In an equation for ‘a’: a = truncate $ fromIntegral 5 / 2
那么,a
的等式是不正确的?让我们修复a
和b
的类型:
number :: Float
number = (a + b) / 2 where
a, b :: Int
a = truncate $ fromIntegral 5 / 2
b = fromIntegral $ 12
现在它变得清晰了:
SO.hs:2:11: Couldn't match expected type ‘Float’ with actual type ‘Int’ In the first argument of ‘(+)’, namely ‘a’ In the first argument of ‘(/)’, namely ‘(a + b)’ SO.hs:2:15: Couldn't match expected type ‘Float’ with actual type ‘Int’ In the second argument of ‘(+)’, namely ‘b’ In the first argument of ‘(/)’, namely ‘(a + b)’ Failed, modules loaded: none.