Composition with dyadic operator?

I want to make something pretty simple; I use the (++) operator with Data.Map insertWith and it works fine, but I want to exclude duplicates in the created value, so I want to compose it using nub.

I tried (nub (++)), (nub $ (++)), (nub. (++)), all to no avail, since the type (++) does not match the expected type nub ([a]).

I could, of course, define an auxiliary function or lambda, but I think that perhaps there is a composition that would be clearer.

Tips, please!

+8
haskell function-composition
source share
5 answers

You can write it like

((nub .) .) (++) 

Example:

 Prelude Data.List> ((nub .) .) (++) [1,2,3] [3,4,5] [1,2,3,4,5] 

In general, do you have

 (f . ) gx = f (gx) ((f . ) . ) gxy = f (gxy) (((f . ) . ) . ) gxyz = f (gxyz) ((((f . ) . ) . ) . ) gxyzv = f (gxyzv) ... 

Here's the conclusion of this identity for ((nub .) .) :

 (f . g) x = f (gx) (nub .) :: Eq a1 => (a -> [a1]) -> a -> [a1] (nub .) = \gx -> (nub (gx)) ((nub .) .) :: Eq a2 => (a -> a1 -> [a2]) -> a -> a1 -> [a2] ((nub .) .) = ((\gx -> (nub (gx))) .) = (\g' x' -> (\gx -> (nub (gx))) (g' x')) = \g' x' x -> (nub ((g' x') x)) 

A good article about this (and related) idiom, but it is in Russian: - (

+10
source share

What you want seems to be part of binary and unary functions, for example:

 compose :: (c -> d) -> (a -> b -> c) -> (a -> b -> d) compose unary binary ab = unary (binary ab) 

And you request a free version (without mentioning variables a and b ). Try and eliminate them one by one. We start with b using the fact that f (gx) = f . g f (gx) = f . g :

 compose unary binary a = unary . binary a 

a next one. First let the desugar expression:

 compose unary binary a = ((.) unary) (binary a) 

And again apply the same rule:

 compose unary binary = ((.) unary) . binary 

This can be written as follows:

 compose unary = (.) ((.) unary) 

Or even how

 compose = (.) . (.) 

Here, each (.) "Shares" the argument with a binary function, and you need two of them, because the function is binary. This idiom is very useful when generalizing to any functor: fmap . fmap fmap . fmap (note that fmap equivalent . when the function is considered as a functor). This allows you to disable any functor, for example, you can write:

 incrementResultsOfEveryFunctionInTwoDimentionalList :: [[String -> Integer]] -> [[String -> Integer]] incrementResultsOfEveryFunctionInTwoDimentionalList = fmap . fmap . fmap $ (+1) 

So your result will be:

 (fmap . fmap) nub (++) 

Edit:

I think I found the answer that my brain was trying to reproduce: The composition operator of a Haskell function like (c → d) → (a → b → c) → (a → b → d)

+6
source share

This problem is solved in a particularly simple and beautiful way with the help of combinators of the semantic editor. Meeting:

Your final composition will look like this:

 (result.result) nub (++) 
+3
source share

You can use a somewhat ridiculous combinator (.).(.) :

 Prelude> :set -XNoMonomorphismRestriction Prelude> :m + Data.List Prelude Data.List> let f = ((.).(.)) nub (++) Prelude Data.List> :tf f :: Eq a => [a] -> [a] -> [a] Prelude Data.List> f "ab" "ac" "abc" 

Most likely, it will be easier to read only lambda or a helper function in where -clause.

+1
source share

I do not think that the composition operator you want exists as one function in any standard library. The shortest way to write this is probably ((.).(.)) . Using the Functor definition for ((->) t) , you can also write it as fmap . fmap fmap . fmap or if you prefer fmap fmap fmap .

All of the above is rather mysterious, but the idiom is widespread enough that many people will find out what you are doing.

By the way, you can avoid calling functions from the two "dyadic" arguments in Haskell, because if you extend this terminology to functions of a single argument, you really will confuse people.

See also this question for some related discussions.

You can also find many combinators with very intuitive names in this library.

+1
source share

All Articles