2016-02-08 21 views
1

我有這個功能刪除參數「e」的一個問題:無法刪除的參數(自由點式的Haskell)

numocc e = map length . (map . filter . (==)) e 

功能檢查內部兩個元素的出現次數的數量維列表(列表中的列表)。所以你怎麼稱呼它,如下所示:

numocc 1 [[1, 2], [2, 3, 2, 1, 1], [3]]

Result : [1,2,0]

參數ê是最右邊等號的兩邊,並且在任何參數不包住。所以,我應該能夠將其刪除,以得到一個免費的點對點功能:

numocc = map length . (map . filter . (==)) 

但是我得到這個錯誤:

Type error in application Expression : map length . map . filter . (==) Term : map length Type : [[b]] -> [Int] Does not match : ([[a]] -> [[a]]) -> [Int]

什麼是這裏的問題?謝謝。

+0

當您在列表上測試函數numocc時,它也會產生一個錯誤。你過濾與平等但等於什麼? –

+1

@ Zacharie007 對不起,我應該澄清一下,此函數計算二維列表中元素的出現次數。所以你可以這樣稱呼它: numocc 1 [[1,2],[2,3,2,1,1],[3]] –

回答

6

你原來的功能被解析爲

numocc e = (map length) . ((map . filter . (==)) e) 

所以你不能只是刪除e,因爲它在技術上不出現在定義的末尾。但是,如果你定義操作

(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d) 
(.:) = (.) . (.) 

然後,你可以把它寫成

numocc = map length .: (map . filter . (==)) 

,因爲你不能混用..:由於固定性規則上map . filter . (==)括號是必需的。

但是,在這一點上,你只是使這個功能更難以閱讀和維護。這將是更好地把它分解成更小的部分,並引入一箇中間的名字,與添加的正確類型的簽名,並給予功能一個更好的名字一起開始:

numOccurrences :: Eq a => a -> [a] -> Int 
numOccurrences valueToCount values = length (filter (== valueToCount) values) 

numOccurrencesInSublists :: Eq a => a -> [[a]] -> [Int] 
numOccurrencesInSublists valueToCount = map (numOccurrences valueToCount) 

這是更具可讀性,沒有按」不要依賴特殊的運營商,更清楚地表達你的意圖。由於在單個列表中計數的情況是單獨的功能,因此您現在可以在其他地方使用它。

請記住,優雅的代碼並不是要儘可能簡短,而是儘可能讓它變得儘可能清晰。描述性名稱(不一定是長的),顯式參數和小型可組合單位是最好的。

+0

謝謝! 但是有沒有其他的方式來做到這一點,而不需要引入新的操作符? 它使該功能看起來更加混亂。 –

+1

@VladyslavBabych檢查我的編輯。我還確保澄清第一個代碼塊中的解析。基本上,不要試圖使用大量的高級操作員,需要發明更多的操作員來有效地使用它們。圓括號通常是最簡單和最易讀的解決方案,在99%的案例中使用顯式參數比無點符號要好。 – bheklilr

+0

@bheklir 我打算接受這個答案,但是這個函數是用於學習的目的(大學),而且這個任務說明我應該用一種無點式的方式來定義它。 但是,您的意見仍然非常有幫助,謝謝!正如我所看到的,如果不引入新的操作員,就不可能實現這一點。 –