2016-05-22 11 views
1

私はMatrix aとして定義された行列のデータ型を持っています。私のプログラムのほとんどの場所では、Matrix Stringのような文字列か、またはMatrix (Matrix a)のような他の行列と一緒に使用します。戻り値の型を拡張する汎用メソッド

特定の規則に従って行列の内容を埋め込む関数を書く必要があります。文字列行列の場合は、

pad :: Matrix String -> Matrix (Matrix String) 

となります。各文字列は特定のサイズの行列に変換されるためです。

それらの他のマトリックスとマトリックスの場合、関数は次のようになります

pad :: Matrix (Matrix a) -> Matrix (Matrix a) 

この場合、インナーマトリックスのサイズのみが変化しているからです。

これら2つを一般化する方法はありますか?私は私のpadを定義しないと予想されるエラー、「文脈から...推測することができませんでした」PaddableとしてStringMatrix aを宣言し、その後

class Paddable b => Paddable a where 
    pad :: a -> Matrix b 

と、これは明白で失敗します。私はこれを試してみました可能なすべての値bをカバーする機能。

ここにはどのような候補がありますか?

答えて

2

パッドの両方のバージョンが概念的に異なることをしているように思われるので、おそらく別の名前にする必要があります。コード内で見た目のパターンを見つけたときに型クラスを定義することは、必ずしも良い考えではありません。

{-# LANGUAGE TypeFamilies, FlexibleInstances #-} 

class Paddable (PaddedContent a) => Paddable a where 
    type PaddedContent a :: * 
    pad :: Matrix a -> Matrix (PaddedContent a) 

instance Paddable String where 
    type PaddedContent String = Matrix String 
    pad = ... 

instance Paddable (Matrix a) where 
    type PaddedContent (Matrix a) = Matrix a 
    pad = ... 
1

署名が

baによって決定される
pad :: Matrix a -> Matrix b 

です。言った... associated type familyと試みたとして、あなたが行うことができます

だから、それはfunctional dependenciesを使用して行うことができます。

{-# LANGUAGE FlexibleInstances, 
      MultiParamTypeClasses, 
      FunctionalDependencies #-} 

data Matrix a = Matrix a deriving Show 

class Paddable a b | a -> b where 
    pad :: Matrix a -> Matrix b 

instance Paddable (Matrix a) (Matrix a) where 
    pad = id -- dummy implementation! 

instance Paddable String (Matrix String) where 
    pad (Matrix str) = Matrix . Matrix $ ">> " ++ str ++ " <<" 

その後:

\> pad $ Matrix (Matrix 42) 
Matrix (Matrix 42) 

\> pad $ Matrix "abc" 
Matrix (Matrix ">> abc <<") 
関連する問題