Haskellで(むりやり)やるオブジェクト指向
Haskellにもclassがあるのだから、C++とかで見るオブジェクト指向もできるでしょうということで、無理やりやってみました...笑って見過ごしてやってください。一応、クラスの継承関係もできるので、ここでは
Object -> Animal -> (Dog, Cat)
という構図になっています。Objectクラスではメンバー関数呼び出し演算子.>を定義して、Animalでは動物特有なメソッドを定義しています。
こうすることで、
d = Dog "Pochi"
d.>name ==> "Pochi"
d.>(soundN 3) ==> "BowowBowowBowow"
みたいなことができるようになります…
module Main where class Object a where (.>) :: a -> (a -> b) -> b (.>) obj mthd = mthd obj class (Object a) => Animal a where name :: a -> String sound :: a -> String soundN :: Int -> a -> String soundN i a = concat $ replicate i (a.>sound) instance (Animal a) => Object a newtype Dog = Dog String instance Animal Dog where name (Dog nm) = nm sound _ = "Bowow" newtype Cat = Cat String instance Animal Cat where name (Cat nm) = nm sound _ = "Meow" d = Dog "Pochi" c = Cat "Tama" namesound :: (Animal a) => a -> (a -> String) -> String namesound an sn = an.>name ++ " " ++ (an.>sn) main = do print $ namesound d sound print $ namesound c (soundN 10)
強いて、学んだことを挙げるとすれば、どうやら、Haskellではクラスとタイプの宣言が別々で、データメンバーはタイプの中にしか表現できないので、メンバーの継承はできなさそげということです...
C++だったら:
class Animal { protected: String m_Name; }; class Dog : public Animal {};
なんてやると、Dogにはm_nameメンバが勝手についてくるのですが、これはできないっぽい?
ではでは。