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 )

+3


source to share


2 answers


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.

+5


source


Can you apply an array of functions to data? For example. you can define:

let apply (arg:'a) (fs:(('a->unit) seq)) = fs |> Seq.iter (fun f -> f arg)

      



Then you should be able to do something like this:

apply 1 [(fun x -> printfn "%d" (x + 1)); (fun y -> printfn "%d" (y + 2))]

      

+3


source







All Articles