使用'/'时没有(Fractional Int)的实例

时间:2018-03-09 01:03:08

标签: haskell

data Tick = Tick
  { _price :: Int
  , _timestamp :: TimeOfDay
  } deriving (Eq, Ord)

instance Num Tick where
  (-) (Tick a b) (Tick a' _) = Tick (a - a') b


calcAxis :: High -> Low -> Int
calcAxis (Just (Tick a _)) (Just (Tick b _)) = (fromIntegral (a - b)) / 2

我知道将Int分开会产生Float,因此我需要在使用Int之前使用fromIntegral转换(/) {1}}但是我仍然会收到错误:

• No instance for (Fractional Int) arising from a use of ‘/’
• In the expression: (fromIntegral (a - b)) / 2
  In an equation for ‘calcAxis’:
      calcAxis (Just (Tick a _)) (Just (Tick b _))
        = (fromIntegral (a - b)) / 2

我真的不明白它要求我做什么。当然,我不必为Fractional Int定义一个实例?

我认为我做错了什么。

2 个答案:

答案 0 :(得分:3)

问题是你在使用/之后最终得到一个浮点数,你的类型规范说你应该返回一个Int。

您需要舍入/截断转换为Int或更改calcAxis的类型签名。

> let a = 1 :: Int
> let b = 2 :: Int
> let c = (fromIntegral (a - b)) / 2
> :t c
c :: Fractional a => a

并且Fractional Int没有实例是类型错误指示的内容。

答案 1 :(得分:3)

正如Ryan评论的那样,将结果保持为小数类型可能是正确的。 {HESell}中Float非常不寻常,通常会选择更高精度Double或精确Rational

calcAxis :: High -> Low -> Double
calcAxis (Just (Tick a _)) (Just (Tick b _)) = fromIntegral (a - b) / 2
calcAxis _ _ = ... -- keep in mind to handle the `Nothing` case as well!

那就是说,如果你有理由做出结果Int,并且总是希望向零舍入,那么只需使用整数除法即可:

calcAxis :: High -> Low -> Int
calcAxis (Just (Tick a _)) (Just (Tick b _)) = (a - b) `quot` 2

......或者,如果你总想要四舍五入,

calcAxis (Just (Tick a _)) (Just (Tick b _)) = (a - b) `div` 2