2012-01-25 26 views
6

C++プログラムと同様のHaskellコードを記述するための問題に取り組んでいます。Haskellで関数のオーバーロードを実装します。

C++コードは:

class Rectangle 
{ 
    private: 
     int length; 
     int width; 
    public: 
     Rectangle() 
     { 
      length = 0; 
      width = 0; 
     } 
     Rectangle(int x) 
     { 
      length = x; 
      width =0; 
     } 
     Rectangle (int x , int y) 
     { 
      length = x; 
      width = y; 
     } 
}; 

同様のHaskellのコードを記述するiは、私はコンストラクタとして作用することができる負荷を機能させると考え

data Rectangle = Rectangle Length Width deriving (Eq, Show , Read) 
type Length = Int 
type Width = Int 

長方形

データ型を作りました。しかし、私は引数の異なる数で関数のオーバーロードを実装する方法を理解していません。 助けてください。ありがとう。

+1

私はC++の後でhaskellをモデル化しようとはしません。それだけで多くの痛みにつながるでしょう。また、2番目の四角形のコンストラクタはなぜ線ですか?私はより賢明な実装は、(1,1)にデフォルトすることになり、1つのintを取得する場合は、(x、x)を渡して正方形を形成すると思います。 – alternative

+0

コンストラクタの初期化リストについて聞いたことがありますか? –

+2

@VladLazarenko:まだ学んでいる人のことを聞いたことがありますか? (ヒント:皆さんの中にいます) –

答えて

21

、そしておそらく後で混乱エラーにつながる:

は今、あなたは、いくつかの Rectangle値を定義することができます。代わりに、あなたは単にデータを構築する関数を定義する必要があります

point :: Rectangle 
point = Rectangle 0 0 

line :: Length -> Rectangle 
line l = Rectangle l 0 

square :: Int -> Rectangle 
square a = Rectangle a a 

これは、あなたがセマンティクス各オーバーロードのを説明する明確な名前を付けることができます、というよりもそのあなたを明確にするために与えられた引数の数と型に頼ります平均。

あなたがオーバーロードされたバージョンを書いてみませんしかし、もし、あなたが型クラスで簡単にそれを行うことができます。

class MakeRectangle a where 
    rectangle :: a 

instance MakeRectangle Rectangle where 
    rectangle = Rectangle 0 0 

instance MakeRectangle (Length -> Rectangle) where 
    rectangle l = Rectangle l 0 

instance MakeRectangle (Length -> Width -> Rectangle) where 
    rectangle = Rectangle 

あなたはこれをコンパイルするために、ファイルの先頭に{-# LANGUAGE FlexibleInstances #-}が必要になります。このようなトリックは標準のText.Printfライブラリで使用されていますが、Haskellでのオーバーロードの特に良い例ではありません。オーバーロードされた値の型にはほとんど常にいくつかの構造がありますが、ここではその構造全体が型推論の方法で得られるインスタンスによって決まります。それだけでなく、インスタンスを支配する合理的な法律はありません(実際、そのタイプは許可するにはあまりにも一般的です)。

しかし、本当にやりたければできますが、通常は悪い考えですが(時にはprintfのように)、それはあなたが望むインターフェイスを達成する唯一の方法です。あなたが明示的に使用している型を指定する必要があります、またはインスタンスを解決することはできません、GHCiの中でこれを試してみ

GHCi> rectangle :: Rectangle 
Rectangle 0 0 
GHCi> rectangle (1 :: Length) :: Rectangle 
Rectangle 1 0 
GHCi> rectangle (1 :: Length) (2 :: Width) :: Rectangle 
Rectangle 1 2 
+0

私はプログラムをコンパイルできません。エラーは '複数の長方形の宣言 'です。 –

+0

インデントを保持していますか?ファイル内の他の部分で 'rectangle'の別の宣言がありますか?それらのどちらでもない場合は、コンパイルしているファイル全体を質問に追加してください。 – ehird

+1

自分のコードのスペースを忘れてしまった。 Haskellはインデントセンシティブ言語です。 – ehird

22

レコード構文を使用して、その動作に到達できます。

data Rectangle = Rectangle {len :: Length, width :: Width} deriving (Eq, Show , Read) 
type Length = Int 
type Width = Int 

rectangle = Rectangle { len = 0, width = 0 } 

rectangle :: Rectangleここにコンストラクタがあります。それはHaskellで、このようなオーバーロードを行うことことは可能ですが、それは慣用考えられていない、

λ> let a = rectangle {len = 1} 

λ> a 
Rectangle {len = 1, width = 0} 
4

は、あなたがしているものではありません単純にこれを探しています:

data Rectangle = Point | Line Int | Rectangle Int Int