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
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 caseandMap << mapCmd msgis 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)
But instead
let
partial = mapCmd msg
in
\x -> andMap (partial x)
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.
> 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’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)
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.