Composing 2 (or n) ('a & # 8594; unit) functions with the same arg type
Is there some form of inline / term, I don't know that its "different" and "different" combine two functions 'a -> unit
to give one; eg:.
let project event =
event |> logDirections
event |> stashDirections
let dispatch (batch:EncodedEventBatch) =
batch.chooseOfUnion () |> Seq.iter project
can be:
let project = logDirections FOLLOWEDBY stashDirections
let dispatch (batch:EncodedEventBatch) =
batch.chooseOfUnion () |> Seq.iter project
and then:
let dispatch (batch:EncodedEventBatch) =
batch.chooseOfUnion () |> Seq.iter (logDirections FOLLOWEDBY stashDirections)
I think one can compare it to tee
(as mentioned in the FSFFAP series on Rail-Oriented Programming ).
(it should pass the same argument for both, and I am trying to run them sequentially, without any problem handling exceptions, etc.)
(I know I can do let project fs arg = fs |> Seq.iter (fun f -> f arg)
, but I'm wondering if there is something built in and / or some form of lib composition, I don't know about )
source to share
apply
Klark's function is the easiest way to solve the problem.
If you want to go deeper and understand the concept as a whole, then you can say that you are taking a sequential composition operation from working on values to working on functions.
First of all, a construct ;
in F # can be thought of as a sequence operator. Unfortunately you cannot use it as one for example. (;)
(since in the second argument it is special and lazy), but we can define our own operator to investigate the idea:
let ($) a b = a; b
So, printfn "hi" $ 1
now is a sequential side-operation composition and some expression that evaluates to 1
, and does the same thing as printfn "hi"; 1
.
The next step is to define a hoist operation that turns a binary operator working on values into a binary operator working on functions:
let lift op g h = (fun a -> op (g a) (h a))
Instead of writing eg. fun x -> foo x + bar x
, you can write lift (+) foo bar
. So you have an easy way to write the same thing - just by using an operation that works with functions.
Now you can achieve what you want using the lift
sequential composition function and operator:
let seq2 a b = lift ($) a b let seq3 a b c = lift ($) (lift ($) a b) c let seqN l = Seq.reduce (lift ($)) l
Functions seq2
and seq3
consist of only two operations, and seqN
performs the same as the Klark function apply
.
It must be said that I am writing this answer not because I think it is useful for implementing things in F # this way, but as you mentioned railroad oriented programming and asked for deeper concepts behind this, it is interesting to see how things are can be written in functional languages.
source to share