Co chcesz wydaje się być kompozycją funkcji podwójnych i pojedynczych, jak to:
compose :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
compose unary binary a b = unary (binary a b)
I poprosić o punkcie wolne wersji (nie wspominając o a
i b
zmiennych). Spróbujmy je wyeliminować jeden po drugim. Zaczniemy b
, wykorzystując fakt, że f (g x) = f . g
:
compose unary binary a = unary . binary a
a
jest obok. Załóżmy desugar pierwszy wyraz:
compose unary binary a = ((.) unary) (binary a)
I zastosować tę samą zasadę kompozycji znowu:
compose unary binary = ((.) unary) . binary
ten można dodatkowo zapisać jako:
compose unary = (.) ((.) unary)
lub nawet
compose = (.) . (.)
Tutaj, każdy (.)
"usuwa" argument z funkcji binarnej i potrzebujesz dwóch z nich, ponieważ funkcja jest binarna. Ten idiom jest bardzo użyteczny, gdy jest uogólniony dla dowolnego funktora: fmap . fmap
(zauważ, że fmap
jest równoważny .
, gdy funkcja jest postrzegana jako funktor). Pozwala to na 'taśmy' każdy funktora off, na przykład można napisać:
incrementResultsOfEveryFunctionInTwoDimentionalList :: [[String -> Integer]] -> [[String -> Integer]]
incrementResultsOfEveryFunctionInTwoDimentionalList = fmap . fmap . fmap $ (+1)
Tak, Twój wynik staje:
(fmap . fmap) nub (++)
Edit:
Chyba znalazłem odpowiedź, którą mój mózg próbował odtworzyć: Haskell function composition operator of type (c→d) → (a→b→c) → (a→b→d)
Bardzo ładne, dzięki - za odpowiedź i wyprowadzenie. (Twoja ostatnia linia wyprowadzania wygląda tak, jakby była w języku rosyjskim !?) – guthrie
taka sama jak '(nub.). (++) ' – user102008