我正在尝试将笛卡尔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

最佳答案

通常,在Haskell中,参数通常不以“ foo(x,y,z)”的形式编写。相反,我们写“ foo x y z”。前者是合法的:它将参数包装为单个值(称为元组)并将其传递,但​​这是不必要的。

错误消息来自该行

beta = atan2 (y, x).


由于库函数atan2的类型而失败,该函数大致

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


这意味着对于作为“ RealFloat”实例的任何类型“ a”(即类型“ Float”和“ Double”),函数“ atan2”都将其中两个作为参数并返回一个新值。 “ RealFloat a => ...”位表示,在类型“ a”的其余部分中,可以是声明为RealFloat类的实例的任何类型。 “ Float”和“ Double”是这些类型的示例。因此,此功能的一种潜在类型是:

atan2 :: Double -> Double -> Double


但是,您所做的是将其视为具有其他类型:

atan2 :: (Double, Double) -> Double


这表示“ atan2”采用单个参数,该参数是包含两个值的元组。类型检查器试图查看整个元组是否是“ RealFloat”的实例(即我们可以用“ atan2”类型替换“ a”的类型之一),但事实并非如此。因此它生成了一条错误消息,说明是这样。

将隐式括号放回去时,将揭示“ atan2 yx”语法和类型签名中的箭头实际发生的情况。“->”类型运算符是右关联的,因此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的一大优势。

关于haskell - 在Haskell中将笛卡尔3d坐标转换为球面3d坐标系,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4144403/

10-11 07:09