Haskell错误没有实例(Floating Int)

时间:2014-07-20 03:56:28

标签: haskell

此代码是为了获得2点之间的距离,但我遇到了问题!

@EduardoLeon更新

rango2 :: Int -> [Int] -> [[Int]] -> [Int]
rango2 a b list = if (verif [(list!!a!!0),(list!!a!!1),(list!!a!!2)] (b)) then [1]
              else [0]

verif :: [Int] -> [Int] -> Bool
verif a b = if ((distance a b) > a!!2) then True
        else False

difference :: Num a => [a] -> [a] -> [a]
difference xs ys = zipWith (-) xs ys

 dotProduct :: Num a => [a] -> [a] -> a
 dotProduct xs ys = sum $ zipWith (*) xs ys

 distance :: Floating a => [a] -> [a] -> a
 distance xs ys = sqrt $ dotProduct zs zs
where
zs = difference xs ys

编辑:我无法将Int更改为Float,因为我正在使用列表进行操作 抛出这个错误!

Proyecto.hs:71:18:
No instance for (Floating Int) arising from a use of `distance'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `(>)', namely `(distance a b)'
In the expression: ((distance a b) > a !! 2)
In the expression:
  if ((distance a b) > a !! 2) then True else False

3 个答案:

答案 0 :(得分:3)

  

我正在搜索,我看到我需要将Int更改为Float?

只需将类型签名更改为Float即可开始工作:

verif :: [Float] -> [Float] -> Bool

您需要更改代码的类型签名,以指示它适用于浮动数据,因为sqrt函数对此进行操作。一个更通用的解决方案是:

verif :: (Floating a, Ord a) => [a] -> [a] -> Bool
verif a b = if (sqrt((((b!!0)-(a!!0))*((b!!0)-(a!!0)))+(((b!!1)-(a!!1))*((b!!1)-(a!!1)))) < a!!3)
            then True
            else if (sqrt((((b!!0)-(a!!0))*((b!!0)-(a!!0)))+(((b!!1)-(a!!1))*((b!!1)-(a!!1)))) == a!!3)
                 then True
                 else False

Haskell不鼓励使用!!函数。我建议你以更实用的方式重写函数。

答案 1 :(得分:3)

回答您的具体问题:与更传统的语言不同,Haskell不会自动将整数转换为浮点数。事实上,Haskell中不存在强制转换的概念。您需要使用函数fromIntegral将整数转换为其他数字类型。您可以在ghci中尝试以下内容:

> let x = 5 :: Integer
> sqrt x

<interactive>:3:1:
    No instance for (Floating Integer) arising from a use of `sqrt'
    In the expression: sqrt x
    In an equation for `it': it = sqrt x
> let y = fromIntegral x :: Double
> sqrt y
2.23606797749979

我还想就您的编码风格提出一些其他建议:

  • 将您的功能分解为更小的功能,完成一件事并做得很好。

  • 函数(!!)遍历链表以查找n个元素。这是一个O(n)操作,如果您打算从同一列表中检索多个元素,则该操作比必要的更昂贵。首选避免多次遍历同一列表的解决方案。

以下是我如何找到两点之间的距离:

difference :: Num a => [a] -> [a] -> [a]
difference xs ys = zipWith (-) xs ys

dotProduct :: Num a => [a] -> [a] -> a
dotProduct xs ys = sum $ zipWith (*) xs ys

distance :: Floating a => [a] -> [a] -> a
distance xs ys = sqrt $ dotProduct zs zs
  where
    zs = difference xs ys

答案 2 :(得分:0)

我建议你重新审视你的设计。 a中列表bverif的含义是什么?看起来你找到了两点之间的距离。您可以创建一个类型:

data Point = Point Double Double

和一个功能

distance :: Point -> Point -> Double

使您的代码更具可读性。

这也应该通过使用where子句或let绑定来消除两次相同的计算。