2014-07-20 43 views
-1

此代碼是獲得2點之間的距離,但我有一個問題!Haskell錯誤沒有實例(浮動INT)

通過@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 

修訂版編輯:我不能改變詮釋爲浮動,因爲即時通訊做與清單業務,目前 拋出這個錯誤!

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 
+0

變化'rango2 ::的類型簽名(浮動一個,奧德一個)=>內部 - >並[a] - > [[a]] - > [a]'使其工作。在回答問題後,將問題轉換爲新的形式會混淆未來的讀者。 – Sibi

+0

縮進在Haskell中很重要。 – pyon

+0

你爲什麼要比較'a !! 2'的距離?在列表之外單獨存儲該值似乎是一個更好的主意。 – pyon

回答

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 
3

我在尋找,我看到了,我需要改變詮釋爲浮動?

類型簽名就變成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鼓勵。我建議你以更有效的方式重寫函數。

+0

' Float'是單精度的,通常你需要'Double'來代替。 (我想,有一些不幸的命名從C等繼承而來。) –

0

我建議你重新訪問你的設計。 verif中的列表ab的含義是什麼?看起來你正在找到兩點之間的距離。您可以創建一個類型:

data Point = Point Double Double 

和功能

distance :: Point -> Point -> Double 

使代碼更易讀。

這也應該消除使用where子句或let綁定進行兩次相同的計算。