私は特殊な数値データ処理ライブラリを開発していますが、修正方法を理解できないというエラーが出てきました。最初に例を示してから問題を説明する方が簡単だと思います。私も奇妙な名前のために謝罪する、私は法的な目的のために難読化しなければならない。multiparam型クラスのあいまいなインスタンスを解決する
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
data MyError = MyError String deriving (Eq, Show)
data MyList = MyList [Double] deriving (Eq, Show)
data NamedList = NamedList String MyList deriving (Eq, Show)
class MyNum a b ret where
myAdd :: a -> b -> Either MyError ret
myLessThan :: a -> b -> Either MyError Bool
instance MyNum MyList Double MyList where
myAdd (MyList xs) x = Right $ MyList $ map (+x) xs
myLessThan (MyList xs) x = Right $ all (< x) xs
instance MyNum NamedList Double NamedList where
myAdd (NamedList n l) x = fmap (NamedList n) $ myAdd l x
myLessThan (NamedList n l) x = myLessThan l x
私はこれをコンパイルしようとした場合、コンパイラはMyList
に使用するMyNum
の特定のインスタンスを把握することはできませんので、私はエラー
No instance for (MyNum MyList Double ret0)
arising from a use of `myLessThan'
The type variable `ret0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there is a potential instance available:
instance MyNum MyList Double MyList
-- Defined at testing_instances.hs:13:10
Possible fix:
add an instance declaration for (MyNum MyList Double ret0)
In the expression: myLessThan l x
In an equation for `myLessThan':
myLessThan (NamedList n l) x = myLessThan l x
In the instance declaration for `MyNum NamedList Double NamedList'
を取得します。 MyNum
の戻り値の型は簡単に導出されるため、myAdd
で動作しますが、myLessThan
の場合はそれを把握することができません。このタイプキャストを使用して、全体的にきめ細かなエラー処理を簡単に追加できるようにしたいと思います。実際のコードには+、 - 、*、/、等価のものがありますので<、< =、>、> = MyNum Double MyList MyList
、MyNum MyList MyList MyList
などのインスタンスをNamedList
として作成します。これを行うより簡単な方法がない限り、多形交換可能演算子を持つことができるようになります。
ただし、使用するインスタンスがわかるように、2番目のインスタンスにmyLessThan
に追加するタイプシグネチャを特定できません。 1つの解決策は算術演算子と比較演算子を2つの別々の型クラスに分割することですが、可能ならばそれを避けたいと思います。
これは私のためのハスケルで以前はよく知られていない構造であり、まさに私が必要としていたものです。ありがとう! – bheklilr
@bheklilrうれしいです。また、いくつかの方法で作業しやすく、より強力なタイプファミリーについて学ぶこともできます。 – jberryman