2015-03-31 79 views
0


我想了解哈斯克爾的功能遞歸,但我有一些問題,與此功能,特別是與foldr功能:哈斯克爾:遞歸在lambda函數

我宣佈一個data形狀的這種方式:

type P = (Int, Int) -- point 
type V = (Int, Int) -- vector 

data Shape = 
    Line P P     -- line characterized by two vertices 
    | Triangle P P P   -- characterized by three triangle vertices 
    deriving (Eq, Show) 

現在,給出的表單列表,我要提取具有更大的面積形狀

maxArea :: [Shape] -> Shape 
maxArea list = maxArea_hlp list 0 

maxArea_hlp :: [Shape] -> Int -> Shape 
maxArea_hlp list areaMax = foldr (\shape currmax -> if ((area shape) > (area currmax)) then shape else (shape:list)) 0 list 

area :: Shape -> Int 
area (Line _ _) = 0 
area (Triangle p1 p2 p3) = 0 
--TODO 

的錯誤是:

Couldn't match expected type Shape with actual type [Shape] 
In the expression: (shape : list) 

錯誤在於lambda函數的「其他」分支,但我不知道如何解決它。

你能幫助我嗎?
感謝所有

+4

'currmax'應該是什麼類型?根據'foldr'的類型簽名('(a - > b - > b) - > b - > [a] - > b'),它應該是數字的(與'0'相同),但是您也調用'area',這表明它應該是'Shape'。這是你的錯誤。爲此使用'foldr'很尷尬。爲什麼不使用'maximumBy'? – Jubobs 2015-03-31 18:33:44

+6

你在if和另一個分支中的[Shape]中的一個分支中返回了一個'Shape',它沒有進行類型檢查。你在這裏使用'foldr'而不是'Data.List.maximumBy'有什麼特別的理由嗎?你甚至沒有使用'areaMax',所以它可能只是'maximumBy(比較區域)','Data.Ord.comparing'。 – bheklilr 2015-03-31 18:35:03

+0

我不能使用函數'maximumBy',因爲我只能使用高階函數;非常感謝,我現在會嘗試修復它。 – 2015-03-31 18:58:19

回答

1

問題是... then shape else (shape:list)

每個函數都有一個返回類型。 lambda函數也是如此。

該lambda需要是a -> b類型。 當您創建if表達式時,它必須從一個類型中產生一個值。 (在這個例子中b

\shape currmax -> if ((area shape) > (area currmax)) 
        then shape   -- this has type Shape 
        else (shape:list) -- this has type [Shape] 

你總是需要確保該類型是正確的(幸好GHC會抱怨)

而且我真的不知道你正在嘗試做

  1. 您通過0作爲累加器功能的起始值,但是(area currmax)您試圖將其用作形狀(area :: Shape -> Int
  2. 問題w ith then (shape:list)是,你想要預先列出形狀,但列表永遠不會改變,因爲它是一個不可變參數,函數不會遞歸調用它自己。

不要失去希望,不要停止嘗試,你不會後悔學習這種編程風格,並使用這種美麗的語言。

也許只是嘗試,有幾十個可供倍(http://book.realworldhaskell.org/read/functional-programming.html#fp.foldl

順便說一句,這是一個偉大的書,你應該在它http://book.realworldhaskell.org/read/

快樂學習看一看使用不同的例子!