我正在尝试将笛卡尔三维坐标系中的一个点转换为球形三维系统。
这是我到目前为止所得到的:
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 :(得分:6)
更一般地说,在Haskell中,参数通常不以“foo(x,y,z)”的形式编写。相反,我们写“foo x y z”。前者是合法的:它将参数包装成单个值(称为元组)并传递它,但它是不必要的。
错误消息来自
行beta = atan2 (y, x).
由于库函数atan2的类型大致为
,因此失败atan2 :: RealFloat a => a -> a -> a
这意味着对于任何类型“a”,它是“RealFloat”的实例(即“Float”和“Double”类型),函数“atan2”将其中两个作为参数并返回一个新参数。 “RealFloat a =&gt; ...”位表示在其余类型中,“a”可以是任何被声明为RealFloat类的实例的类型。 “浮动”和“双重”是这些类型的示例。因此,此功能的一种潜在类型是:
atan2 :: Double -> Double -> Double
然而,你所做的就是将它视为具有不同的类型:
atan2 :: (Double, Double) -> Double
这表示“atan2”采用单个参数,这是一个包含两个值的元组。类型检查器试图查看整个元组是否是“RealFloat”的实例(即我们可以用“atan2”类型替换“a”的类型之一),并发现它不是。所以它生成了一条错误消息,说明了这一点。
当你将隐式括号放回来时,“atan2 y x”语法和类型签名中的箭头实际上会发生什么。“ - &gt;” type运算符是右关联的,因此atan2的类型实际上是:
atan2 :: Double -> (Double -> Double)
(注意:为简单起见,我省略了“RealFloat a”业务。)这表示“atan2”接受一个参数并返回一个需要第二个参数的新函数。
现在让我们将隐式括号放入调用中。函数应用程序是左关联的,因此“beta”的定义看起来像这样;
beta = (atan2 x) y
遵循从里到外评估括号的规则,这将函数“atan2”应用于“x”并获得一个新函数作为结果,然后应用于“y”,结果给出“beta”。看看类型和表达式如何相互映射?
这不仅仅是一个理论上的伎俩:我可以写一些像
这样的东西myBeta = atan2 x
...
beta = myBeta y
甚至
betas = map myBeta ys
其中“ys”和“betas”是值列表。能够做这样的事情是Haskell的强大优势之一。
答案 1 :(得分: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