2

デカルト 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から

4

2 に答える 2

6

より一般的には、Haskellでは引数は通常「foo(x、y、z)」の形式で書かれていません。代わりに「fooxyz」と書きます。前者は合法です。引数を単一の値(タプルと呼ばれる)にまとめて渡しますが、不要です。

エラーメッセージは行から来ました

beta = atan2 (y, x).

ライブラリ関数atan2のタイプが原因で、これは失敗しました。

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

これは、「RealFloat」のインスタンスであるタイプ「a」(つまり、タイプ「Float」と「Double」)の場合、関数「atan2」はそれらの2つを引数として取り、新しいものを返すことを意味します。「RealFloata=>...」ビットは、残りのタイプで「a」がクラスRealFloatのインスタンスであると宣言された任意のタイプである可能性があることを示します。「Float」と「Double」はこれらのタイプの例です。したがって、この関数の1つの潜在的なタイプは次のとおりです。

atan2 :: Double -> Double -> Double

しかし、あなたがしたことは、それが別のタイプを持っているかのように扱うことでした:

atan2 :: (Double, Double) -> Double

これは、「atan2」が2つの値を含むタプルである単一の引数を取ることを意味します。タイプチェッカーは、このタプル全体が「RealFloat」のインスタンス(つまり、「atan2」のタイプで「a」の代わりに使用できるタイプの1つ)であるかどうかを確認しようとしましたが、そうではないことがわかりました。そのため、そう言うエラーメッセージが生成されました。

「atan2yx」構文、および型シグネチャの矢印で実際に行われていることは、暗黙の角かっこを元に戻すと明らかになります。「->」型演算子は右結合であるため、atan2の型は次のようになります。実際に:

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

(注:簡単にするために、「RealFloat a」ビジネスは省略しています。)これは、「atan2」が引数を取り、2番目の引数を期待する新しい関数を返すことを示しています。

次に、暗黙の角かっこを呼び出しに入れましょう。関数適用は結合性のままなので、「ベータ」の定義は次のようになります。

beta = (atan2 x) y

括弧を裏返しに評価する規則に従って、これは関数「atan2」を「x」に適用し、結果として新しい関数を取得します。次に、「y」に適用され、結果として「ベータ」を与えます。タイプと式がどのように相互にミラーリングされているかを確認してください。

これは単なる理論上のトリックではありません。次のようなものを書くことができます。

myBeta = atan2 x
...
beta = myBeta y

あるいは

betas = map myBeta ys

ここで、「ys」と「betas」は値のリストです。このようなことができることは、Haskellの大きな強みの1つです。

于 2010-11-10T18:09:15.000 に答える
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

2つの間違いがありました。最初は

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

どちらであるべきか

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

2番目は

beta  = atan2(y,x)  

どちらであるべきか

beta = atan2 x y
于 2010-11-10T12:54:27.440 に答える