0

以下のhaskellコードはコンパイルされます。

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius

以下のコードに沿って何かを書くことは可能ですか(コードはコンパイルに失敗します):

data LengthQty = Radius Float | Length Float | Width Float   
data Shape = Circle Point Radius

この試みの背後にある考え方は、半径、長さ、および幅が物理量の長さを表すということです。

次のように書かれている場合は、2番目の部分の2行目に注意してください

data Shape = Circle Point LengthQty

次に、コンパイルしますが、その場合、「LengthQty」は、長さ、幅、半径など、半径のみが必要なものにすることができます。

(1)第2部の何が問題になっていますか?
(2)物理量の長さ(LengthQty)のアイデアを実装するためにどのように修正できますか?

4

3 に答える 3

2

これはコンパイルされます:

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius

data LengthQty = R Float | Length Float | Width Float   

Radius型の名前であり、 type のデータ コンストラクターの名前でもありますFloat -> RadiusR型のデータ コンストラクタですFloat -> LengthQty。同じ名前の 2 つの異なるデータ コンストラクターを持つことはできません。名前は既に 取 られ て います .Radius

以下も機能します。

data LengthQty = R Radius | Length Float | Width Float 

がなければRRadiusそれ自体がタイプ のデータ コンストラクターに:: LengthQtyなり、再び と衝突しRadius :: Float -> Radiusます。

于 2012-07-19T18:29:36.463 に答える
2

コードがコンパイルされない理由は、データ宣言の右側がコンストラクターであり、その後にのリストが続く必要があるためです。つまり、次の形式です。

data {-type-} = {-constructor-} {-type-} ... {-type-}

あなたの例では、定義すると

data LengthQty = Radius Float | Length Float | Width Float 

あなたはタイプを作成LengthQtyしましたが、コンストラクターです。したがって、あなたが書くときRadiusLengthWidth

data Shape = Circle Point Radius

コンパイラはフォームの何かを見ます

data {-type-} = {-constructor-} {-type-} {-constructor-}

つまり、型を予期しているコンストラクターが表示されるため、エラーがスローされます。元のコードでは、シンボルRadiusはコンストラクターと型の両方に使用されていました。コンパイラが見たとき

data Shape = Circle Point Radius

このコンテキストでは型でなければならないことがわかっているため、コンストラクターの半径Radiusと混同する可能性はありません。

これを念頭に置いて、次のように記述するだけで、コードを正しくコンパイルできます。

data Shape = Circle Point LengthQty

そして、円の特定のインスタンスを取得できます

circle :: Shape
circle = Circle (Point 0 0) (Radius 1)
于 2012-07-19T18:20:35.283 に答える
0

の有用な違い

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius


data LengthQty = Radius Float | Length Float | Width Float

Haskell の型システムがそれらを処理する方法です。Haskell には強力な型システムがあり、関数が処理可能なデータを確実に渡すようにします。のような定義を書く理由は、関数ができない、、またはLengthQuantityのいずれかを取ることができる関数がある場合です。 RadiusLengthWidth

、、またはを取ることができる関数があった場合、次のようにタイプを記述します。 RadiusLengthWidth

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius

data LengthQty = R Radius
               | L Length 
               | W Width

このように、関数はRadiusそのより具体的な型チェックからのみ恩恵を受けることができます。

于 2012-07-19T19:44:56.770 に答える