 # Help needed to fully understand << operator

So I think I have done my homework when it comes to elm basics
and recently I have started using the https://github.com/rogeriochaves/spades framework
and at the core of the Main there is a function called

``````andMapCmd : (msg1 -> msg2) -> Return msg1 model1 -> Return msg2 (model1 -> model2) -> Return msg2 model2
andMapCmd msg =
andMap << mapCmd msg
``````

My understanding of the << function composition operator is that

`andMap<< mapCmd msg`

is actually equivelant to

``````let
partial = mapCmd msg
in
andMap(partial)
``````

But somehow this changes the types radically and the compiler complains
anybody care to explain what is my missconception on the operator ?

Hi,

The `<<` operator is function composition, which just means applying one function and then another one.
So `(f << g) x` is equivalent to `f ( g x )`. Or `f << g`` is equivalent to`\x -> f ( g x )`, or, in your case`andMap << mapCmd msg`is equivalent to`\x -> andMap (mapCmd msg x)`.

Using `<<` you’re composing by applying the right hand function first followed by the second. The arrows are supposed to indicate the flow of the argument.

Often `<<` is used to avoid writing down the name of an argument.

It’s probably easiest with a concrete example:

``````incr x = x + 1
decr x = x - 1
constant = incr << decr
decr 10 -- is equal to 9
incr 9 -- is equal to 10
incr (decr 10) -- also equal to 10
constant 10 -- also equal to 10
``````

The `constant = incr << decr` is equivalent to `constant x = incr (decr 10)`

What may be confusing you in your example is that although `andMap << mapCmd msg` is equal to `andMap << (mapCmd msg)`, the `mapCmd msg` is still a function. So if you want to write out the equivalent it is not as you suggested:

``````let
partial = mapCmd msg
in
andMap(partial)
``````

``````let
partial = mapCmd msg
in
\x -> andMap (partial x)
``````

Or in the original:

``````andMapCmd : (msg1 -> msg2) -> Return msg1 model1 -> Return msg2 (model1 -> model2) -> Return msg2 model2
andMapCmd msg m =
andMap (mapCmd msg m)
``````
1 Like

`andMap << mapCmd msg` is actually `(andMap << mapCmd) msg` you first have the composition and then the resulting function receives the `msg` argument.

This can trigger all sorts of compiler errors because in a lot of cases what people actually want is to compose partially applied functions (e.g. `andMap << (mapCmd msg)` ).

You need to pay extra attention if the functions you are trying to compose with `<<` are not unary functions.

Hi,

I initially thought the same as that, but:

``````> incr x = x + 1
<function> : number -> number
> decr x = x - 1
<function> : number -> number
> incr << decr 10
-- TYPE MISMATCH ----------------------------------------------------------- elm
...
> inc << (decr 10)
-- TYPE MISMATCH ----------------------------------------------------------- elm
...
> (incr << decr) 10
10 : number
``````

So `incr << decr 10` is the same as `incr << (decr 10)` and not `(incr << decr) 10`

I still need some time to process it but
since the sinipet

``````let
partial = mapCmd msg
in
\x -> andMap (partial x)
``````

works the same
it’s much more easier for me to understand.
I think my biggest problem was that I overlooked the fact that msg is also a function

Thank you

1 Like

I’m consfused, the repl snapshot points to the fact that only `(incr << decr) 10` is valid.

If you put parentheses like `(decr 10)` you will not get a function but a value.

This is why I said that it is tricky. You can put parentheses if you have a binary function. In that case you will partially evaluate the binary function and get back an unary function that you can use with `<<`

To use a similar example:

``````incr x = x +1
decrBy by x = x - by

incrByOneAfterDecrBy5 =  incr << (decrBy 5)
``````

expanded you have:

`incrByOneAfterDecrBy5 x = incr (decrBy 5 x)`

Hi,

Yes, and we know that `incr << decr 10` is also invalid, therefore it is only possible that `incr << decr 10` is equivalent to `incr << (decr 10)`, if it were equivalent to `(incr << decr) 10` then it would compile, but it doesn’t.

So my point was, that `andMap << mapCmd msg` is equivalent to `andMap << (mapCmd msg)`, and not `(andMap << mapCmd) msg`.

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.