使用'it'时没有(Fractional a0)的实例

时间:2016-09-12 17:02:29

标签: haskell

我正在写一个函数,但我找不到合适的解决方案。我该如何解决这个问题:

findLoot val [] = 0
findLoot val ((x:y:[]):xs) | val == 0 = 0.0
                           | val < y  = ((val*x)/y)
                           | val > y  = ((div val y)*x) + (findLoot (mod val y) xs)

错误是

 interactive:33:1:
     No instance for (Fractional a0) arising from a use of ‘it’
     The type variable ‘a0’ is ambiguous
     Note: there are several potential instances:
       instance HasResolution a => Fractional (Fixed a)
         -- Defined in ‘Data.Fixed’
       instance Integral a => Fractional (Ratio a)
         -- Defined in ‘GHC.Real’
       instance Fractional Double -- Defined in ‘GHC.Float’
       ...plus one other
     In the first argument of ‘print’, namely ‘it’
     In a stmt of an interactive GHCi command: print it

输入集

Input 1:-
  val = 50
  ((x:y:[]):xs) = [[120, 30], [100,50],[60, 20]]
Output 1:-
  180.0000

Input 2:-
val = 10
((x:y:[]):xs) = [[500,30]]
Output 2:- 
166.6667

1 个答案:

答案 0 :(得分:3)

问题是Haskell只能对相同类型的值进行算术运算。当您执行x + yx * yx == y时,xy必须具有相同的类型。

第二个问题是Haskell的数值类型(主要)分为两类,即整数和分数。只有整数类型(例如Integer)支持divmod,并且只有小数类型(例如Double)支持/

您的代码尝试将divmod/xyval一起使用,这会强制Haskell使用寻找一个分数和积分的单一类型。这种类型不存在。

这是一个可能的解决方案:

findLoot :: Integer -> [[Integer]] -> Double
findLoot val [] = 0
findLoot val ((x:y:[]):xs) | val == 0 = 0.0
                           | val < y  = fromIntegral (val * x) / fromIntegral y
                           | val > y  = fromIntegral (div val y * x) + findLoot (mod val y) xs

此处所有输入(valxy)均为Integer,这使divmod正常工作,结果是Double。每当需要小数(对于/并且要添加到递归findLoot调用的结果)时,fromIntegral用于将Integer转换为Double