2016-05-03 3 views
1

「唯一の可能性のあるインスタンスを使用する」というタイプクラスメソッドのためのHaskell言語拡張はありますか?あいまいなタイプのデフォルトインスタンスを選択

私は、次の

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances  #-} 

class Foo a r where 
foo :: a -> r 


instance Foo a (Bool -> a) where 
    foo x _ = x 

-- This compiles 
-- bar :: Int -> Bool 

-- This does not 
bar :: a -> Bool 
bar _ = True 


use :: Bool 
use = bar $ foo _5 True 
    where 
    _5 :: Int 
    _5 = 5 

をコンパイルしたい今、私は次のエラーを取得:

 No instance for (Foo Int (Bool -> r0)) 
    (maybe you haven't applied enough arguments to a function?) 
    arising from a use of ‘foo’ 
The type variable ‘r0’ is ambiguous 
Note: there is a potential instance available: 
    instance Foo a (Bool -> a) -- Defined at tests/pos/Fixme.hs:9:10 

をしかし、一つだけの潜在的インスタンスが利用可能であることから、使用するGHCを強制する方法がありますそのインスタンス?または、型があいまいであるときに、既定のインスタンスとしてインスタンスを宣言する方法がありますか?

+3

このtypeclass +インスタンスは私をひどくします。ここに正しいことを表現していますか? –

答えて

3

標準トリックは、このように、あなたのインスタンスは、それ以上の多型にすることです:

instance (a ~ b, bool ~ Bool) => Foo a (bool -> b) where 
    foo x _ = x 

これは、他の機能のインスタンスを書くことからあなたを排除するが、関数インスタンスが望まれるとき、それは明確にどのような種類を使用することができます。これを行うには、拡張子TypeFamiliesをオンにする必要があります。特定のケースでは、ただちにinstance a ~ b => Foo a (Bool -> b)で他の引数型の関数インスタンスを使用できるようになり、より頻繁にあいまいなエラーが発生する可能性があります。

このトリックの詳細については、a previous answer of mineを参照してください。

+0

ダニエルありがとう!私は 'ブール'をそのまま残すことができます!以下は十分です! foo a(Bool - > b)where foo x _ = x' – Niki

+0

なぜこのトリックが動作するのか理解しようとしています: インスタンスは非常に一般的なのでインスタンスは型チェッカーによって "受け入れられ"、そして_then_制約 'a〜b'がチェックされていますか? 私の最初の例では、 'r'が' Int'にインスタンス化されないようにするものです。 – Niki

+0

@ Niki正しい例:インスタンスの選択中にインスタンスコンテキスト( '=>'の左側にあるもの)は無視されます。あなたの例では、 'r'が' Int'にインスタンス化されることを妨げるものは何もありませんが、何もそれを強制しません。誰かが潜在的に後に来て、例えば以下のようなインスタンスを定義する可能性があるからです。 'インスタンスFoo Int(Bool - >())'のように、既存のインスタンスが正しいインスタンスであるかどうかは不明です。現在のモジュールがコンパイルされていることを条件に一致するのは唯一のものですが、オープンワールドの前提は、後でコンパイル単位を追加できることを意味します。 –

関連する問題