2011-12-15 14 views
3

私は単純なクラスAClassを公開しており、オーバーライドできる公開メンバーf1があります。 AClassの新しいインスタンスを別のメンバーf2と定義する方法は何ですか?AClassのソースコードを複製するのは簡単ですか?以下玩具コード:新しいメンバーでクラスインスタンスをオーバーライドする

class AClass a where 
    f1 :: a -> Int 

data Val = I Int 

instance AClass Val where 
    f1 x = 0 

    -- the method below can't be added as it is not public member of AClass 
    -- f2:: a -> Float 
    -- f2 x = 0.0 

私は周りを見回したが、私はそれを行う方法上の任意の明確な例を見つけられませんでした(すなわち、例として、私にはよく理解できた - 明瞭度は相対的です)。可能な方法は何ですか?クロージャー、新しいタイプの宣言など?上記のおもちゃコードで技術を説明すると便利です(ラッパーをIntに置き換えるなど)data宣言などを変更できますが、上記のコードでは不変なのはクラス宣言AClassです。これは、クラスがすでにライブラリライターによって書かれていることを前提としているため、私はそれに触れません。最終結果はAClassの特典を継承し、f2のメンバーを追加する別のおもちゃコードでなければなりません。

もちろん、このようなオーバーライドクラスでは注意が必要です。しかし、それは可能なことと、それがどういうものかを知るのに役立ちます。

- 更新 -

以下の作業コード - いくつか欠けている部分があった - - 解決策を考え出すためのベンとmergeconflictの功績下記に記入:

class AClass a where 
    f1 :: a -> Int 

class (AClass a) => BClass a where 
    f2 :: a -> Float 

data Val = I Int 

instance AClass Val where 
    f1 _ = 0 

instance BClass Val where 
    f2 _ = 0.0      

答えて

9

達成しようとしていることは何ですか?

Valのタイプがあり、AClassというインスタンスを作成しています。 Valを使用する任意の数の関数を定義することができます。これらの関数は、クラスとは何の関係もありません。 instance宣言で定義しようとしないでください。

あなたがAClassインスタンスを使用し、それらをf2を呼び出すことができる持っている機能で使用余分f2機能を有しているAClassの一つの特定のインスタンスを持つことができるようにすることです何を期待している...それはだ場合不条理定義上、すべてのAClassインスタンスに共通することがわかっているのは、AClassで宣言されたものだけです。いくつかの価値について知っているのは、それがAClassのインスタンスであるタイプのメンバーであるということであれば、AClassのすべてのインスタンスではできないことは何もできません。特定のインスタンスに特有の余分なものを呼び出すことはできません。

あなたはAClassがないだけでなく、f2する操作のすべてをサポートしてい新しいクラスを作成し、Valが、あなたはちょうどそれを...その新しいクラスのインスタンスで持つようにしたい場合。

class AClass a => AnotherClass a where 
    f2 :: a -> Float 

instance AnotherClass Val where 
    f2 x = 0.0 
+0

@ dave4420:この例で編集していただきありがとうございます。 – Ben

+0

はい、AClassの操作をサポートするクラスで、f2は機能します。しかし、私があなたのアプローチを試してみると、AnotherClassの目に見えないメンバーではないというf1のエラーが出ます。 f1とf2の両方の実装はインスタンスに残されており、エラーがどこから来るのかが分かります。 – Sal

+0

'class AClass a => AnotherClass a where ...'は 'AnotherClass'のインスタンスになる前に 'a'型が' AClass'のインスタンスでなければならないことを示します。あなたがそのような宣言をしていないならば、それはあなたの誤りでしょう。 – comingstorm

4

あなたがすべきハスケルはオブジェクト指向ではなく、オブジェクト指向のクラスではありません。

単純に関数f2 _ = 0.0を定義することができます。あなたが定義に追加しない限り、それはtypeclass AClassのメンバーではありませんが、なぜそれが必要なのですか?

+0

ありがとう。明確にするために、私はOOPの観点からそれを求めていません。問題は、Haskellで可能なこととその方法についてです。 – Sal

5

あなたの質問は本当にHaskellで意味がありません。

は、私はオーバーライドすることができ、パブリックメンバーf1と単純なクラスAClassを持っていると言います。

「オーバーライド可能な」「パブリックメンバー」を「クラス」と考えている場合は、オブジェクト指向の用語を考えています。あなたが示したコードは、それらの概念をまったく表現していません。 (それがすべてで助けている場合、C++ sense中)"Type-classes are nothing like interfaces."

型クラスコンセプトを定義トニー・モリスの記事を参照してください。

class Eq a where 
    (==) :: a -> a -> Bool 

を...しかし、実際の行動や、これらの機能の実装:その概念は、例えば、いくつかの機能セットで構成されます。ここでは「オーバーライド」するものは何もありません。だから、あなたのような多型のアルゴリズムを実装することができます

data Integer = {- ... -} 
instance Eq Integer where 
    x == y = x `integerEq` y 

data Float = {- ... -} 
instance Eq Float where 
    x == y = x `floatEq` y 

:今

allEqual :: Eq a => a -> a -> a -> Bool 
allEqual a b c = (a == b) && (b == c) 

、バックあなたの質問になって、あなたはまた、タイプを定義することができますモデルこの概念は次のように、インスタンス宣言を提供するデータの種類より具体的な概念であるをモデル化するクラス以前に定義された型クラスよりも。たとえば:だから

class (Eq a) => Num a where 
    (+), (-), (*) :: a -> a -> a 

は、NumのインスタンスではありませんEqのインスタンスがありますが、Numのすべてのインスタンスは、Eqのインスタンスでなければなりません。

class AClass a where 
    f1 :: a -> Int 

class (AClass b) => BClass b where 
    f2 :: a -> Float 

data Val = {- whatever -} 
instance BClass Val where 
    f1 _ = 0 
    f2 _ = 0.0 

ここでも、Valは「継承グッズ」はそれ自体が、ちょうどそれがBClassのインスタンスおよびこれもAClassのインスタンスだと言っていますされていません:あなたの例では、このような何かをしたいかもしれません。しかし、これは明らかにおもちゃのコードです...

+0

OPのOOの考え方をよく聞きます – luqui

+0

@mergeconflict、はい、あなたの言葉で、 "以前に定義された型クラスよりも具体的な概念をモデル化"しようとしています。あなたが投稿したコードの最後のスニペットは、この問題を解決することに関連しています(Benが投稿したコードに似ています)。問題は、コンパイラがf1がBClassの可視メンバではないと不平を言うため、Valのインスタンス宣言でf1を実装できないことです。では、インスタンス宣言にf1とf2を実装させるにはどうすればよいですか? – Sal

関連する問題