2012-06-17 26 views
5

Tôi đang tìm hiểu về DT đại số trong haskell. Những gì tôi muốn làm là tạo ra một ADT mới mà loại "mở rộng" một hiện có. Tôi không thể tìm thấy cách thể hiện những gì tôi muốn, ai đó có thể sugest một mô hình thay thế hoặc sugest một giải pháp. Tôi muốn chúng là những loại riêng biệt, nhưng chỉ sao chép và dán các đường nối như một giải pháp ngớ ngẩn. Mã dưới đây mô tả đúng nhất những gì tôi đang tìm kiếm.Loại dữ liệu đại số của Haskell: "pseudo-extend"

data Power = 
    Abkhazia | 
    -- A whole bunch of World powers and semi-powers 
    Transnistria 
    deriving (Eq, Show) 

data Country = 
    --Everything in Power | 
    Netural | 
    Water 
    deriving (Eq, Show) 

Chỉnh sửa: Tôi nghĩ rằng Nó cần một chút làm rõ ... Tôi muốn để có thể làm được điều này (trong ghci)

let a = Abkhazia :: Country 

và không

let a = Power Abkhazia :: Country 
+1

Lý do muốn làm điều này thường đến từ một trường OO-y suy nghĩ ;-), nhưng bạn luôn có thể thêm một hàm tạo trong phạm vi Quốc gia cho PowerCountry đang nắm giữ một Power. –

+0

Hmm tôi có thể hỏi Abkhazia và Transnistria được đưa vào một đoạn mã Haskell không? Làm thế nào bạn có liên quan với hai nơi đó? Bạn đang làm việc trên một số loại trò chơi? Bạn đến từ quốc gia nào? –

+0

Abkhazia và Transnistria là người đầu tiên và cuối cùng trong danh sách "Các tiểu bang khác" trên http://en.wikipedia.org/wiki/List_of_sovereign_states Tôi chỉ học Haskell và đưa ra một cái gì đó để thực hành. Tôi đoán nó có thể là một trò chơi, nhưng tôi chưa có ý định. –

Trả lời

8

Bạn cần phải đại diện cho họ dưới dạng cây:

data Power 
     = Abkhazia 
     | Transnistria 
    deriving (Eq, Show) 

    data Country 
     = Powers Power -- holds values of type `Power` 
     | Netural  -- extended with other values. 
     | Water 
    deriving (Eq, Show) 

Chỉnh sửa: tiện ích mở rộng của bạn cho câu hỏi làm cho việc này đơn giản hơn một chút: cả hai loại Quốc gia và Nguồn đều có chung một số hành vi là "quốc gia". Điều này cho thấy bạn sử dụng tính năng mở rộng, mở rộng loại của Haskell để đưa ra các hành vi phổ biến cho kiểu dữ liệu. Ví dụ.

data Power = Abkhazia | Transistria 

    data Countries = Neutral | Water 

sau đó, một lớp kiểu cho điều cả điện và nước cổ phần:

class Countrylike a where 
     landarea :: a -> Int -- and other things country-like entities share 

    instance Countrylike Power where 
     landarea Abkhazia = 10 
     landarea Transistria = 20 

    instance Countrylike Countries where 
     landarea Neutral  = 50 
     landarea Water  = 0 

sau đó bạn có thể sử dụng landarea sạch ở hai cường quốc hoặc quốc gia. Và bạn có thể mở rộng nó sang các loại mới trong tương lai bằng cách thêm nhiều phiên bản khác.

+0

Đây gần như là những gì tôi muốn, nhưng hãy xem xét làm rõ. Cảm ơn! –

+1

@Raisdead bạn _can't_ làm điều đó trong Haskell, và Don sẽ biết, ... (Tuy nhiên, bạn có thể sử dụng các lớp kiểu đa tham số để mô phỏng phân lớp, điều này có thể là ý của bạn. Trong mọi trường hợp, câu trả lời của Don có lẽ là tốt nhất bạn sẽ nhận được, và những gì bạn nên sử dụng.) –

2
{-# LANGUAGE GADTs, StandaloneDeriving #-} 
data POWER 
data COUNTRY 

data CountryLike a where 
    Abkhazia :: CountryLike a 
    Transnistria :: CountryLike a 
    Netural :: CountryLike COUNTRY 
    Water :: CountryLike COUNTRY 

deriving instance Show (CountryLike a) 
deriving instance Eq (CountryLike a) 

type Power  = CountryLike POWER 
type Country = CountryLike COUNTRY 

foo :: Power 
foo = Abkhazia 

bar :: Country 
bar = Abkhazia 

baz :: Country 
baz = Netural 

Edit: Một thay thế sẽ là type Power = forall a. CountryLike a (Ưu điểm: Làm cho Power Nhược điểm một subtype của Country:. Điều này sẽ làm cho ví dụ Power -> Int một loại hạng cao hơn, mà có xu hướng gây phiền nhiễu (loại suy luận vv))

Các vấn đề liên quan