2011-04-27 55 views
2

我剛開始學習Haskell,並且在調整語言時遇到問題,例如在執行map時更具體地嘗試執行類似下面的示例操作;Haskell Map功能實現問題

rotate :: Dimensions -> imgBlock -> [(imgBlock,Int)] 
rotate d ((p, pix), s, t) 
    = zip [((p, f pix), s, t) | f <- transformate (fst d)] [0..7] 

makeAllRotations :: Dimensions -> [imgBlock] -> [(imgBlock,Int)] 
makeAllRotations d ib = map concat (rotate d ib)    //Error points Here 

type imgBlock = (Block, Int, Int) 
type Block = (Pnt, Pxl) 
type Dimensions = (Int, Int) 

這是錯誤的,我得到

asdf.hs:73:30: 
    Couldn't match expected type `(imgBlock, Int)' 
       with actual type `[a0]' 
    Expected type: [[a0]] -> (imgBlock, Int) 
     Actual type: [[a0]] -> [a0] 
    In the first argument of `map', namely `concat' 
    In the expression: map concat (rotate d ib) 

之一,我發現自己很沮喪,努力適應這種新的編程「範式」,其中大部分的我設法做的事情是通過試驗和錯誤。我顯然不能正確理解map,雖然我已經閱讀了關於這個website的文檔,但是所有的例子在map (2+) [1,2,3]這樣的控制檯中都顯示出來,而不是在功能中使用它們。

我可以通過我的map實現瞭解哪裏出錯。 THKS

+4

一個好主意是命名中間值,使用'where'語法並且給所有事物賦予類型簽名。這迫使你思考(反對試驗和錯誤)。不要對haskell失去希望!如果你願意調整你的思維模式,它會報答你很好。 :) – Tarrasch 2011-04-27 19:21:32

+3

我第二@ Tarrasch的建議。在學習Haskell時,如果需要的話,它可以幫助我們儘可能多地完成中間步驟:如果沒有其他任何東西,它就會澄清你的想法。最終,您可以省略越來越多的類型,並讓編譯器推斷它們。如果你寫了'map concat x where x :: ...'並試圖通過x的類型進行推理,那麼不用'map concat(rotate d ib)',你*可能已經發現了這個bug。或者學會解釋錯誤:它表示'concat'是實際類型'[[a0]] - > [a0]'(你知道),它不能與'[[a0]] - >' (imgBlock,Int)'。 – ShreevatsaR 2011-04-27 19:39:15

+2

@Tarrasch,@ShreevatsaR;人們非常感謝你的建議和支持,這真的意味着世界在這樣的挫折時刻。我當然在實踐中提出了你的建議,顯然我需要找到一種方法來習慣像Haskell這樣的聲明性語言。再一次感謝 – pondigi 2011-04-27 20:16:39

回答

4

找到問題的最好辦法是看類型:

rotate :: Dimensions -> ImgBlock -> [(ImgBlock,Int)] 
makeAllRotations :: Dimensions -> [ImgBlock] -> [(ImgBlock,Int)] 
map :: (a -> b) -> [a] -> [b] 
concat :: [[a]] -> [a] 

map函數試圖調用在每個的CONCAT(ImgBlock,智力)在列表中對由旋轉返回。但是concat希望得到一個嵌套列表作爲它的參數。但是幫助我弄清楚如何解決這個問題的重要事情是看着rotate d ib。旋轉的第二個參數是ImgBlock,但在這種情況下ib :: [ImgBlock]。預計單個項目時,您無法傳入列表。但這是地圖功能的用途。它允許你接受一個接受單個項目的函數(上面類型簽名中的'a')並在你有[a]時使用該函數。我懷疑你想要的是這樣的:

makeAllRotations d ib = concat $ map (rotate d) ib 

由於旋轉返回一個列表,map (rotate d) ib返回一個列表的列表,這完全符合作爲第一個參數的concat函數。

+0

得到它,我不得不說我不熟悉'$'操作符,但我想我現在;) – pondigi 2011-04-27 20:17:28

+1

連接列表返回函數映射到列表的結果是很常見的,它有自己的函數'concatMap': 'makeAllRotations d ib = concatMap(rotate d)ib',或者無點:'makeAllRotations = concatMap。 rotate' – pat 2011-04-28 02:54:21