2012-01-25 64 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代碼我犯了一個數據類型矩形

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

然後我認爲使得其可以作爲構造作用的負荷的功能。但我不明白如何用不同數量的參數實現函數重載。 請幫忙。謝謝。

+1

我不打擾試圖在C++之後對haskell建模;它只會導致很多痛苦。另外,爲什麼你的第二個矩形構造函數是一行?我認爲一個更明智的實現是默認爲(1,1),如果你得到一個int,傳入(x,x),形成一個正方形。 – alternative

+0

有沒有聽說過構造函數初始化列表? – 2012-04-21 02:56:14

+2

@VladLazarenko:曾聽說過仍在學習的人嗎? (提示:你是其中的人,每個人都是) –

回答

21

雖然可能在Haskell做這樣的重載,它沒有考慮習慣,並可能會導致混亂的錯誤以後。相反,你應該簡單地定義構造數據功能:

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將成爲您的構造函數。

現在你可以定義一些Rectangle值:

λ> let a = rectangle {len = 1} 

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

是不是你是什麼尋找簡單的這個:

data Rectangle = Point | Line Int | Rectangle Int Int