【问题标题】:No instance for (Fractional a0) arising from a use of ‘it’没有因使用“it”而产生 (Fractional a0) 的实例
【发布时间】:2016-09-13 02:23:32
【问题描述】:

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

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

【问题讨论】:

  • 看起来像可怕的单态限制(谷歌这个词) - 它试图确定你的数字的类型,但不能决定一个。
  • @Bergi 有没有办法修改这个?我想不出合适的解决方案。
  • 添加显式类型findLoot :: Fractional a =&gt; a -&gt; [a] -&gt; a
  • @Bergi 添加此内容后,我在加载时遇到错误无法将预期类型“a”与实际类型“[a]”匹配,“a”是受约束的刚性类型变量findLoot :: Fractional a => a -> [a] -> a 的类型签名
  • 同时使用 div/ 看起来不对。你的号码是什么类型的?您可能只需要/(浮点)或只需要div(整数除法)。

标签: haskell


【解决方案1】:

问题在于 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)都是Integers,这使得divmod工作,结果是Double。每当需要小数时(对于/ 和添加到递归findLoot 调用的结果),fromIntegral 用于从Integer 转换为Double

【讨论】:

  • 值得注意的是,您明​​确声明类型将使编译器给出更多信息错误。好的做法是有回报的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 2016-11-26
相关资源
最近更新 更多