Haskell - 无法理解这种类型的不匹配错误

时间:2015-03-06 11:59:35

标签: haskell types

我有以下代码(yyyymm定义为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只是StringPhonePad[(Char, Int)]Date(Int, Int, Int)

1 个答案:

答案 0 :(得分:3)

好吧,truncate的类型为(RealFrac a, Integral b) => a -> b,这意味着其多态结果需要满足Integral约束。但是,dowNumber的类型表示(partOne + partTwo) / 7Float。因此,partOnepartTwo 需要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的等式是不正确的?让我们修复ab的类型:

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.