2013-05-08 12 views
7

Tôi đang sử dụng typeclass sau:Làm cách nào để yêu cầu Haskell không nhập cùng một cá thể từ hai mô-đun?

module T where 
class T a where 
    v :: a 

Một thể hiện của T Int mà tôi thực hiện:

import T 
import A (av) 

instance T Int where 
    v = 0 

main = putStrLn (av ++ show v) 

Và một module mà tôi muốn sử dụng một giá trị từ, mà còn có một thể hiện của T Int.

module A where 
import T 
instance T Int where 
    v = 0 
av = "value from A" 

Vấn đề là điều này không làm việc:

$ runghc Main.hs 

Main.hs:4:9: 
    Duplicate instance declarations: 
     instance T Int -- Defined at Main.hs:4:9-13 
     instance T Int -- Defined at A.hs:3:9-13 

Haskell phàn nàn rằng có 2 tờ khai cho các trường hợp tương tự. Làm cách nào tôi có thể yêu cầu anh ta không nhập khẩu cá thể từ B hoặc để hợp nhất cả hai trường hợp hoặc chỉ sử dụng cá thể từ Main?

+1

Đừng làm điều này. Giải pháp thích hợp là chỉ khai báo cá thể ở một nơi. – hammar

+0

@hammar: Tôi không viết 'T' hoặc' B', nhưng tôi muốn sử dụng giá trị từ 'B', và tôi muốn tạo một thể hiện' T'. – Dog

+1

Ah, điều đó làm cho nó phức tạp hơn. Trong trường hợp đó, bạn có thể tạo một 'newtype' gói kiểu hiện có và viết thể hiện của bạn cho' newtype' để thay thế. – hammar

Trả lời

8

Thật không may, bạn không thể kiểm soát cách các trường hợp được nhập và xuất; xem Do Haskell imports have side effects?.

Điều này có nghĩa là bạn sẽ phải cấu trúc lại mã của mình để đảm bảo rằng cá thể chỉ được xác định trong một tệp. Nói chung, tốt nhất là chỉ định nghĩa một cá thể trong tệp định nghĩa lớp hoặc kiểu dữ liệu - trên thực tế, thậm chí có một cảnh báo về các cá thể "mồ côi" không tuân theo quy tắc này. (Hãy xem Orphaned instances in Haskell để có một cuộc thảo luận dài về lý do tại sao bạn nên tránh các trường hợp trẻ mồ côi.)

Tuy nhiên, nếu không thể, bạn vẫn có thể tự ý chọn một trong các tệp để giữ nó hoặc thậm chí tạo mô-đun mới được nhập bởi tất cả các tệp cần có cá thể cụ thể đó.

Tổng quát hơn, làm thế nào bạn sẽ đối phó với khả năng rằng hai trường hợp đã thứ khác nhau, như:

instance T Int where v = 0 
{- And in a different file: -} 
instance T Int where v = 1 

Có thực sự là không ngay lập tức rõ ràng cách để disambiguate hai mà không thay đổi đáng kể cách thức Haskell hệ thống typeclass hoạt động.

Vì bạn đã tự viết một trong các trường hợp, chỉ cần xóa một trong các trường hợp đó. Vì nó giống với định dạng được xác định trước, chỉ cần nhập mô-đun đó bất cứ nơi nào bạn cần sử dụng.

+0

"Điều này có nghĩa là bạn sẽ phải cấu trúc lại mã của bạn để đảm bảo rằng cá thể chỉ được xác định trong một tệp." Tôi có thể làm cái này như thế nào? Tôi không viết 'T' hay' B'. – Dog

+0

Ồ. Sau đó, yeah, nó xấu. Đây là lý do tại sao bạn không phải viết các thể hiện trẻ mồ côi. Tôi sẽ gửi một lỗi về điều này với các mô-đun có thể hiện trẻ mồ côi - đó là, một trong đó có trường hợp mà không xác định hoặc là lớp hoặc loại. –

+2

@Dog: Thật ra, có lẽ tôi đã hiểu lầm vấn đề của bạn. Vì bạn đã viết một trong các trường hợp, chỉ cần xóa nó. Viết nó cho một 'newtype' nếu bạn có. –

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