2012-01-04 18 views
30

明示的にtypeclassインスタンスをインポートするにはどうすればよいですか?また、どのように資格を持った輸入品でこれを行うのですか?インスタンスを明示的にインポートします。

現在、私は(Either String)に使用できるモナドのインスタンスをインポートする

import Control.Monad.Error() 

をやっています。 Monadインスタンスが暗黙的にインポートされるので、以前、私は、私はどちらかと満足していない

import Control.Monad.Error 

を使用しました。

答えて

45

インスタンスのインポートを制御できないことは、Haskellのtypeclassシステムが行うトレードオフの1つです。ここでは仮想的なHaskellの方言の例だところ、次のことができます。

Foo.hs:

module Foo where 

data Foo = FooA | FooB deriving (Eq, Ord) 

Bar.hs:

module Bar (myMap) where 

import Data.Map (Map) 
import qualified Data.Map as Map 

import Foo 

myMap :: Map Foo Int 
myMap = Map.singleton FooA 42 

Baz.hs:

module Baz where 

import Data.Map (Map) 
import qualified Data.Map as Map 

import Foo hiding (instance Ord Foo) 
import Bar (myMap) 

instance Ord Foo where 
    FooA > FooB = True 
    FooB > FooA = False 

ouch :: Map Foo Int 
ouch = Map.insert FooB 42 myMap 

Yikes!セットmyMapは適切なinstance Ord Fooで作成されましたが、相違すると異なるで作成されたマップと組み合わせられています。

これを行うことができれば、Haskellのオープンワールドの仮定に違反します。残念ながら、私はそれについて学ぶための良い、中央集権的なリソースを知らない。このsection of RWHが役に立つかもしれません(私は "haskell open world assumption"を検索しました)。

+0

マップ、セットではありません。良い例、+1。 –

+0

@DanielFischer:固定、ありがとう:) – ehird

+3

そのパスに行きたい場合は、マップがそのOrd辞書を持ち運びできるように、インスタンスをファーストクラスにする必要があります。 –

7

できません。インスタンスは常に暗黙的にエクスポートされるため、明示的にインポートすることはできません。ちなみに、Either eMonadインスタンスは今日はControl.Monad.Instancesになります。

2

一般的に正しい答えは「いいえ、することはできません」となりますが、私はこの恐ろしいソリューションを提案:

コピー+ペースト

は、所望のライブラリのソースコードを見てみましょうモジュールを作成し、必要なデータ宣言、インポート、および関数定義を独自のコードにコピー/ペーストします。 不要なインスタンスをコピーしないでください。これはおそらくbaseライブラリですべての問題を解決することはできませんけれども

当面の問題によっては、ghc type system extensionsOverlappingInstancesまたはIncoherentInstancesは、別の解決策になるかもしれません。

+1

マットは、 'import Foo(バー、インスタンスBazを隠している)'より 'import Foo(インスタンスバーBaz)'のようなものをむしろ言うことができたかったと思います。 –

+0

@ダニエルフィッシャー - そうです。しかし、そのようなことが絶対に必要な場合は、私が考えることができる「プランB」のソリューションはコピー&ペーストだけです。 '{ - #ThisInstanceTrumps# - } 'のようなコメントを追加して、GHCが他のインスタンスを選択するのではなく、あなたのインスタンスを使用するようにしても良いでしょう。 –

+4

うわー、これは本当に恐ろしい提案です。あなたが残した唯一のことは、オリジナルとあなたのコピー/貼り付けられた定義との間の相互運用に 'unsafeCoerce'を使用することです。 –