2013-05-08 3 views
7

Я использую следующий класс типов:Как сказать Haskell не импортировать один и тот же экземпляр из двух модулей?

module T where 
class T a where 
    v :: a 

Экземпляр T Int что я реализовал:

import T 
import A (av) 

instance T Int where 
    v = 0 

main = putStrLn (av ++ show v) 

И модуль, который я хочу использовать значение из, который также имеет экземпляр T Int.

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

Проблема заключается в том, это не работает:

$ 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 жалуется, что есть 2 объявлений для одного экземпляра. Как я могу сказать ему, чтобы он не импортировал экземпляр из B, или для объединения обоих экземпляров, или использовать экземпляр только с Main?

+1

Не делайте этого. Правильное решение - объявить экземпляр только в одном месте. – hammar

+0

@hammar: Я не писал 'T' или' B', но я хочу использовать значение из 'B', и я хочу создать экземпляр' T'. – Dog

+1

А, это делает его более сложным. В этом случае вы можете сделать 'newtype' завершение существующего типа и вместо этого записать ваш экземпляр для' newtype'. – hammar

ответ

8

К сожалению, вы не можете контролировать, как экземпляры импортируются и экспортируются; см. Do Haskell imports have side effects?.

Это означает, что вам придется реорганизовать свой код, чтобы убедиться, что экземпляр определен только в одном файле. В общем, лучше всего определить экземпляр в файле, который определяет либо класс, либо тип данных. Фактически существует даже предупреждение о случаях «сирота», которые не следуют этому правилу. (Посмотрите на Orphaned instances in Haskell для долгого обсуждения вопроса о том, почему вам следует избегать случаев сироты.)

Однако, если это по какой-то причине невозможно, вы можете просто произвольно выбрать один из файлов, чтобы сохранить его или даже создать новый модуль для импорта всеми файлами, нуждающимися в этом конкретном экземпляре.

В целом, как бы вы иметь дело с возможностью того, что два экземпляра сделал различные вещи, как:

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

Существует действительно не сразу очевидный способ устранения неоднозначности эти два без существенного изменения, как Haskell работает система виджетов.

Поскольку вы написали один из примеров самостоятельно, просто удалите его. Поскольку это то же самое, что и предопределенный, просто импортируйте этот модуль там, где вам нужно его использовать.

+0

«Это означает, что вам придется реорганизовать свой код, чтобы убедиться, что экземпляр определен только в одном файле». Как я могу это сделать? Я не писал 'T' или' B'. – Dog

+0

Ох. Тогда да, это плохо. Вот почему вы не должны писать экземпляры сироты. Я бы установил ошибку об этом с модулем с экземпляром orphan, то есть тем, у которого есть экземпляр без определения класса или типа. –

+2

@Dog: На самом деле, может быть, я неправильно понял вашу проблему. Поскольку вы написали один из экземпляров, просто удалите это. Напишите его для 'newtype', если вам нужно. –

 Смежные вопросы

  • Нет связанных вопросов^_^