any*_*ody 2 haskell coordinate-systems
我试图将笛卡尔三维坐标系中的一个点转换为球形三维系统.
这是我到目前为止所得到的:
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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
哪个没用.到底是怎么回事?
转换公式来自http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
更一般地说,在Haskell中,参数通常不以"foo(x,y,z)"的形式编写.相反,我们写"foo xy z".前者是合法的:它将参数包装成单个值(称为元组)并传递它,但它是不必要的.
错误消息来自该行
beta = atan2 (y, x).
Run Code Online (Sandbox Code Playgroud)
由于库函数atan2的类型大致是失败的
atan2 :: RealFloat a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
这意味着对于任何类型"a",它是"RealFloat"的实例(即"Float"和"Double"类型),函数"atan2"将其中两个作为参数并返回一个新参数."RealFloat a => ..."位表示在其余类型中,"a"可以是任何被声明为RealFloat类实例的类型."浮动"和"双重"是这些类型的示例.因此,此功能的一种潜在类型是:
atan2 :: Double -> Double -> Double
Run Code Online (Sandbox Code Playgroud)
然而你所做的就是把它当作不同的类型来对待它:
atan2 :: (Double, Double) -> Double
Run Code Online (Sandbox Code Playgroud)
这表示"atan2"采用单个参数,该参数是包含两个值的元组.类型检查器试图查看整个元组是否是"RealFloat"的实例(即我们可以用"atan2"类型替换"a"的类型之一),并发现它不是.所以它生成了一条错误消息.
当您将隐式括号放回时,"atan2 yx"语法和类型签名中的箭头实际上会发生什么." - >"类型运算符是右关联的,因此atan2的类型是其实:
atan2 :: Double -> (Double -> Double)
Run Code Online (Sandbox Code Playgroud)
(注意:为简单起见,我忽略了"RealFloat a"业务.)这表示"atan2"接受一个参数并返回一个需要第二个参数的新函数.
现在让我们将隐式括号放入调用中.函数应用程序是左关联的,因此"beta"的定义如下所示;
beta = (atan2 x) y
Run Code Online (Sandbox Code Playgroud)
遵循从里到外评估括号的规则,这将函数"atan2"应用于"x"并获得新函数作为结果,然后将其应用于"y",从而给出"beta"作为结果.看看类型和表达式如何相互映射?
这不仅仅是一个理论上的伎俩:我可以写出类似的东西
myBeta = atan2 x
...
beta = myBeta y
Run Code Online (Sandbox Code Playgroud)
甚至
betas = map myBeta ys
Run Code Online (Sandbox Code Playgroud)
其中"ys"和"betas"是值列表.能够做这样的事情是Haskell的强大优势之一.
更正代码:
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
Run Code Online (Sandbox Code Playgroud)
有两个错误,首先是在
radialDistance3D (x,y,z) = sqrt (x*2 + y*y + z*z)`
Run Code Online (Sandbox Code Playgroud)
应该是
radialDistance3D (x,y,z) = sqrt (x*x + y*y + z*z)
Run Code Online (Sandbox Code Playgroud)
第二个是
beta = atan2(y,x)
Run Code Online (Sandbox Code Playgroud)
应该是
beta = atan2 x y
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1792 次 |
最近记录: |