2010-11-10 34 views
2

我試圖將笛卡爾三維座標系中的一個點轉換爲球形3d系統。在haskell中從笛卡爾3d轉換爲球形3d座標系

這是我走到這一步:

radialDistance3D (x,y,z) = sqrt (x*2 + y*y + z*z) 

cartesian3DToPolar3D (x,y,z) = (r,alpha, beta) 
           where r  = radialDistance3D (x,y,z) 
             alpha = acos(z/r) 
             beta = atan2(y,x) 

GHCI加載代碼,但是當我嘗試用

cartesian3DToPolar3D(1.0,2.0,3.0)

執行它,我得到:

<interactive>:1:0: 
    No instance for (RealFloat (t, t)) 
     arising from a use of `cartesian3DToPolar3D' 
        at <interactive>:1:0-33 
    Possible fix: add an instance declaration for (RealFloat (t, t)) 
    In the expression: cartesian3DToPolar3D (1.0, 2.0, 3.0) 
    In the definition of `it': 
     it = cartesian3DToPolar3D (1.0, 2.0, 3.0) 

這不是有幫助的。到底是怎麼回事?

轉換公式從http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates

+0

不要緊,我知道了:)它是atan2 yx,而不是atan2(y,x) – anybody 2010-11-10 12:29:32

+3

不應該''radialDistance3D(x,y,z)'='sqrt(x * x + y * y + z * z)',而不是'= sqrt(x * 2 + y * y + z * z)'!? – adamse 2010-11-10 12:39:44

+0

既然你已經知道了,爲什麼不在SO上寫一個答案呢? – 2010-11-10 12:47:12

回答

5

更正代碼:

radialDistance3D (x,y,z) = sqrt (x*x + y*y + z*z) 

cartesian3DToPolar3D (x,y,z) = (r,alpha, beta) 
           where r  = radialDistance3D (x,y,z) 
             alpha = acos(z/r) 
             beta = atan2 y x 

有兩個錯誤,第一次是在

radialDistance3D (x,y,z) = sqrt (x*2 + y*y + z*z)` 

這應該是

radialDistance3D (x,y,z) = sqrt (x*x + y*y + z*z) 

第二次是

beta = atan2(y,x) 

這應該是

beta = atan2 x y 
+0

將此標記爲答案 – 2010-11-10 13:07:42

+0

您可以在2天內接受您自己的答案:) – anybody 2010-11-10 13:18:41

6

更一般地,在Haskell參數不正常寫入的形式爲 「foo(X,Y,Z)」。相反,我們寫「foo x y z」。前者是合法的:它將參數包裝成單個值(稱爲元組),並通過它,但它不必要。

錯誤消息從線路

beta = atan2 (y, x). 

這失敗,因爲庫函數ATAN2的類型,這是大致的

atan2 :: RealFloat a => a -> a -> a 

這意味着來,對於任何類型的「一個」,其是「RealFloat」的一個實例(即類型「Float」和「Double」),函數「atan2」將其中的兩個作爲參數並返回一個新的參數。 「RealFloat a => ...」位表示在其餘類型中,「a」可以是任何聲明爲RealFloat類實例的類型。 「浮動」和「雙」是這些類型的例子。因此,一個潛在的類型,這個功能是:

atan2 :: Double -> Double -> Double 

但是你做了什麼,是把它當作雖然它有不同的類型:

atan2 :: (Double, Double) -> Double 

這是說「ATAN2」需要一個參數這是一個包含兩個值的元組。類型檢查器試圖查看這個整個元組是否是「RealFloat」的一個實例(即我們可以用「atan2」類型替換「a」的類型之一),並且發現它不是。所以它產生了一個錯誤消息,說這樣。

「atan2 yx」語法和類型簽名中的箭頭實際上發生了什麼,當您將隱式括號放回時會顯示。「 - >」類型運算符是正確關聯的,所以ATAN2的類型實際上是:

atan2 :: Double -> (Double -> Double) 

(注:爲簡單起見,我要離開了「RealFloat」業務。)這是說「ATAN2」需要一個參數,並返回一個新的功能,預計第二個參數。

現在讓我們把隱式括號放入調用中。函數應用程序是關聯的,因此「beta」的定義如下所示;

beta = (atan2 x) y 

按照由內而外的評估括號的規則,適用的功能「ATAN2」爲「X」,並且獲得新功能的結果,然後將其應用到「Y」給「公測」結果是。看看類型和表達式是如何鏡像的?

這不只是一個理論上的把戲:我可以寫類似

myBeta = atan2 x 
... 
beta = myBeta y 

甚至

betas = map myBeta ys 

其中「伊蘇」和「貝塔」是值的列表。能夠做到這一點是Haskell的強項之一。

相關問題