定义所需的分数Int实例

时间:2014-07-08 15:21:11

标签: haskell

time :: Int -> (Int,Int,Int)
time x = ((x/3600),(x`mod`3600)/60,((x`mod`3600)`mod`60))   

定义时间所需的分数Int实例

expample =

时间x =(小时,分钟,秒)

时间3600 =(1,0,0)

给出一个秒的时间,必须在示例中显示它(小时,分钟,秒)3600是1h 0m 0s

3 个答案:

答案 0 :(得分:5)

我相信您收到该错误是因为您使用带有/参数的Int运算符。您可以使用div来消除错误,如下所示:

time :: Int -> (Int,Int,Int)
time x = ((x `div` 3600),(x `mod` 3600) `div` 60,((x `mod` 3600) `mod` 60))  

正如其他人所指出的那样,(/)要求参数为Fractional,而div则对Integral值感到满意。

答案 1 :(得分:4)

您不能对整数使用常规除法运算符。在数学和Haskell中都是如此,因为除数仅在数学结构为Field时才有效。整数没有定义除法,但你可以执行类似的名为整数除法(是的,误导性的名称)或截断的除法。这是在Haskell中使用div函数实现的,您可以将其用作:

time :: Int -> (Int, Int, Int)
time x = (x `div` 3600, (x `mod` 3600) `div` 60, (x `mod` 3600) `mod` 60)

此处,我只是简单地将/的每个实例替换为其中缀形式的div,否则不会更改您的算法。


那么实现/运算符的类型意味着什么?如果我们加载GHCi:

> :info (/)
class Num a => Fractional a where
    (/) :: a -> a -> a
    ...
        -- Defined in 'GHC.Real'
infixl 7 /

这告诉我们/Fractional类型类的成员,实现它的任何东西也必须实现Num类型类。简而言之,可以分割的东西必须是分数。 Fractional类型类中还有什么?

> :info Fractional
class Num a => Fractional a where
    (/) :: a -> a -> a
    recip :: a -> a
    fromRational :: Rational -> a
instance Fractional Float
instance Fractional Double

因此,Fractional数字具有除法,倒数运算和Rational数字的转换。理想情况下,a * recip a == a / a == 1,因为我们熟悉的分数集(理性,实数,复数)都是如此。

答案 2 :(得分:3)

它向您显示错误的原因是(/)具有以下类型:

λ> :t (/)
(/) :: Fractional a => a -> a -> a

因此,它只接受并返回小数字,例如Float和Double。解决此问题的一种方法是使用div函数,其类型为div :: Integral a => a -> a -> a

time x = ((x `div` 3600),(x`mod`3600) `div` 60,((x`mod`3600)`mod`60))

解决此问题的另一种方法是对将应用于fromIntegral函数的数字使用/函数,并在返回时执行正确的类型转换:

time :: Int -> (Int, Int, Int)
time x = (a,b,c)
  where a = ci $ fi x / fi 3600
        b = ci $ fi (x `mod` 3600) / fi 60
        c = (x `mod` 3600) `mod` 60
        fi = fromIntegral
        ci = ceiling