2013-01-09 17 views
5

aşağıdaki iki tür düşünün:Haskell alan adlarını farklı ad boşluklarına nasıl yerleştirirsiniz?

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

ghc derleyici şikayet olduğunu Meydanı bununla Dikdörtgen çatışmalarda upperLeft alan adı. Bu, her alan adının türün ad alanında olması gerektiği gibi görünüyor, aksi halde alan adlarını yeniden kullanamazsınız ve bunun yeterince ortak bir beklenti olacağından şüpheleniyorum. Biz her alan adı kendi türü ad alanı içinde olması gerektiğini beklemek yapabilmelidir görebilirsiniz Bundan

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

: Biz yazma bir değişken tanımlamak için Örneğin

.

Kullanımım doğru mu, yoksa beklentilerim yanlış mı? Bunu düzeltmek için bir yer var mı?

cevap

3

Haskell'de, bir kayıt türü oluşturma ayrıca erişimci işlevleri de oluşturur. Örneğin, almak için yukarıda tanımladığınız değişkenlerin herhangi birinde x (upperLeft a) çalıştırabilirsiniz. summary of record syntax.

Seçenekler, kayıttaki farklı alan adlarını kullanmak veya bunları ayrı modüllere koymak için kullanılır. Modüllerin her birinin kendi ad alanı olduğundan, Kare modülüne Kare ve Dikdörtgen Modülü içine Kare koyarsanız, alan adlarını yeniden kullanabilirsiniz.

+1

Her türün kendi modülüne yerleştirilmesi aşırı bir şey gibi görünüyor. Erişim fonksiyonlarının yaratıldığını anladım, ancak daha sonra tür çıkarımının kullanılacak doğru alan adını seçeceğini umuyordum. –

+0

Evet, bu durumda modüllere ayrılmanın aşırı hız gibi hissettiğine katılıyorum. Muhtemelen alan isimlerini değiştiririm. RectUpperLeft gibi bir şey, "upperLeft" den daha uzun bir ton değildir. Alan adlarını yeniden kullanmanın beklediğiniz faydalı ve makul bir şey gibi göründüğünü kabul ediyorum, ancak bildiğim kadarıyla bunu Haskell'in kayıtları ile yapamazsınız. – astrieanna

2

Kare tipi kurucuyu Dikdörtgen türüne koymanız mümkün olabilir, çünkü bu türden bir uzmanlık alanı gerçekten çok fazla.

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) 

Sonra ikisi çağırabilirsiniz: Eğer Meydanı değiştirmek isteyebilirsiniz rağmen

upperLeft s 
upperLeft r 

bazı kısıtlamaları vardır çünkü GHCi dışarı şeyler yazarak itibaren

, bu çok iyi çalışıyor görünüyor Karşılıklı olması gerekenler:

data Rectangle 
    = Rectangle {upperLeft::Point, bottomRight::Point} 
    | Square {upperLeft::Point, size::Float} 
    deriving (Eq, Show) 
4
Nesneleri alan adlarıyla erişebildiğinden mpiler, bir nesnenin türünü alan adından çıkarabilmelidir. Örneğin,

boundingBox x = bottomRight x - upperLeft x 

erişimciler bottomRight ve upperLeft içinde x türünü ortaya çıkarabileceği için kullanılır. Eğer birden çok türün aynı erişimci ismine sahip olmasına izin verilmişse, bu türden bir sonuç elde etmek mümkün olmazdı.

İsim çarpışmalarından kaçınmak için, genel bir kural tüm alan adlarına bir önek koymaktır. Bu sözleşme GHC projesinde kullanılmaktadır.

data Rectangle = {rc_upperLeft :: Point, rc_bottomRight :: Point} 
data Square = {sq_upperLeft :: Point, sq_bottomRight :: Point} 
İlgili konular