2013-01-09 17 views
5

は、次の2つのタイプを考えてみましょう:異なる名前空間にhaskellフィールド名を配置する方法は?

data Point=Point{x::Float,y::Float} 
data Rectangle = {upperLeft::Point, bottomRight::Point} 
data Square = {upperLeft::Point, bottomRight::Point} 

GHCコンパイラは文句を言い、その広場のそれと長方形の競合における左上のフィールド名。これは、それぞれのフィールド名がその型の名前空間になければならないという点では奇妙に思えます。そうでなければ、フィールド名を再利用することはできません。我々は、各フィールド名は、それぞれのタイプの名前空間内でなければならないことを期待することができるはずであることがわかります。このことから

let a=Rectangle{upperLeft=Point 2 3, bottomRight=Point 7 7} 
let a=Square{upperLeft=Point 2 3, bottomRight=Point 7 7} 

:私たちは書き込み変数を定義するために例えば

私の使用法は正しいですか?私の期待は間違っていますか?これを修正するために幾分か?

答えて

3

ハスケルでは、レコード型を作成することでアクセサー関数も作成されます。 たとえば、上で定義したいずれかの変数にx (upperLeft a)を実行すると、2になります。 ここにはsummary of record syntaxがあります。

オプションは、レコードに異なるフィールド名を使用するか、レコードを別々のモジュールに入れるかのいずれかです。モジュールにはそれぞれ独自の名前空間がありますので、RectangleモジュールのSquareモジュールとRectangleにRectangleモジュールを入れると、フィールド名を再利用できます。

+1

それぞれのタイプを独自のモジュールに配置することは、過剰なものに見えます。アクセサー関数が作成されたことに気付きましたが、タイプ推論で正しいフィールド名を選択することを望んでいました。 –

+0

はい、私はモジュールに分割するこのケースでは、過剰な使用のように感じることに同意します。私はフィールド名を変更するだけだろう。 'rectUpperLeft'のようなものは' upperLeft'より長いトンではありません。 私はフィールド名の再利用が有用で妥当なものと思われることに同意しますが、私が知る限り、あなたはハスケルの記録でそれを行うことはできません。 – astrieanna

2

Square型のコンストラクタをRectangle型に置くことは、実際にはその型の特殊化されているからです。

GHCiの中のものを入力してから、これは正常に動作するようです:

data Point 
    = Point{x::Float,y::Float} 
    deriving (Eq, Show) 

data Rectangle 
    = Rectangle {upperLeft::Point, bottomRight::Point} 
    | Square {upperLeft::Point, bottomRight::Point} 
    deriving (Eq, Show) 

let r = Rectangle (Point 3.0 4.0) (Point 4.0 2.0) 
let s = Square (Point 2.0 4.0) (Point 4.0 2.0) 

その後、あなたは両方を呼び出すことができます。

upperLeft s 
upperLeft r 

それはいくつかの制約があるので、あなたは広場を変更したいかもしれないがそれは満たす必要があります:

data Rectangle 
    = Rectangle {upperLeft::Point, bottomRight::Point} 
    | Square {upperLeft::Point, size::Float} 
    deriving (Eq, Show) 
4

オブジェクトはフィールド名でアクセスできるため、 mpilerはフィールド名からオブジェクトの型を推測できる必要があります。例えば、

boundingBox x = bottomRight x - upperLeft x 

アクセサbottomRightupperLeftxの種類を推測するために使用されます。複数の型が同じアクセサー名を持つことが許されていれば、その型を推論することはできません。

名前の衝突を避けるため、一般的な規則はすべてのフィールド名に接頭辞を付けることです。このコンベンションは、GHCプロジェクトで使用されています。

data Rectangle = {rc_upperLeft :: Point, rc_bottomRight :: Point} 
data Square = {sq_upperLeft :: Point, sq_bottomRight :: Point} 
関連する問題