這是因爲filter
是一個兩參數函數。你可以解決這個獲得使用便捷的操作
(.:) = (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = (.) . (.)
-- Important to make it the same precedence as (.)
infixr 9 .:
unique = ((== 1) . length) .: filter
如果你看一下在GHCI (length .)
類型,你會得到
(length .) :: (a -> [b]) -> a -> Int
這意味着它需要一個單個參數功能返回一個列表。如果我們看一下filter
類型:
filter :: (a -> Bool) -> [a] -> [a]
這可以被改寫,使其「單參數」作爲
filter :: (a -> Bool) -> ([a] -> [a])
這很清楚不a -> [b]
排隊!尤其是,編譯器無法弄清楚如何使([a] -> [a])
與[b]
相同,因爲一個是列表上的函數,另一個只是列表。所以這是類型錯誤的來源。
有趣的是,.:
運營商可以推廣到函子上工作,而不是:
(.:) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
(.:) = fmap fmap fmap
-- Since the first `fmap` is for the (->) r functor, you can also write this
-- as (.:) = fmap `fmap` fmap === fmap . fmap
這是什麼好處?假設你有一個Maybe [[Int]]
,你希望每個子表的總和Just
內設置了它的存在:
> let myData = Just [[3, 2, 1], [4], [5, 6]]
> sum .: myData
Just [6, 4, 11]
> length .: myData
Just [3, 1, 2]
> sort .: myData
Just [[1,2,3],[4],[5,6]]
或者,如果你有一個[Maybe Int]
什麼,你想增加每個:
> let myData = [Just 1, Nothing, Just 3]
> (+1) .: myData
[Just 2,Nothing,Just 4]
可能性繼續下去。基本上,它可以讓你在兩個嵌套的函子內映射一個函數,這種結構經常會出現。如果您曾經在Maybe
或列表中的元組中有一個列表,或者IO
返回了一個字符串或類似的東西,那麼您遇到了可以使用(.:) = fmap fmap fmap
的情況。
'unique =(== 1)。:length。:filter'也是可能的。另一方面'(== 1)。長度。:filter ::(Num([a] - > Int),Eq([a] - > Int))=>(a - > Bool) - > Bool'可能會檢測,但是沒用。 – Lambdageek 2014-09-04 22:46:01