Continuing the Pipeline With Tee

I always seem to end up writing the same adapter functions over and over again when starting a new project. The functions are usually one or two lines and could easily just be used as lambdas throughout the application. I have found that giving these small functions a name can help make things more succinct. A lot of those functions can be found in FSharpx.Extras, specifically in Prelude.fs.


You’ve written your application and have a nice clean pipeline to define the flow of your operations. All of a sudden you need to add a side-effect in the middle of that pipeline. It could be a log to file, console, or even send some events. We have some choices on how to handle this. We can break the pipes into multiple blocks with let expressions and then evaluating the side-effect. There is nothing wrong with this approach, and may be the best solution. In some simple cases we can use the tee function.

let tee (f : 'a -> unit) x =
    f x

The tee function acts like a plumbing “T” connector allowing the contents to pass through the side-effect without breaking the pipeline. We can see tee is a higher order function that takes a function as a parameter. It then calls the passed in function with the secondary parameter as its argument. We are disregarding the resulting evaluation and then returning x.

A small example would be adding debug logging.

let processData (outputLogger : 'a -> unit) someKey =
    |> getData
    |> transformData
    |> tee outputLogger
    |> finalProcessing

We have a processData function that takes a logging function as an argument. We then wedge the outputLogger into our pipeline using the tee adapter function.

We could have used a lambda to hook in the logging. I’ve done that in the past and still on occasion. I do believe there is value in knowing the names of these small and specialized functions. They have one purpose and do it well. I find I don’t have the mental overhead of entering the lambda when coming back to the code at a later date.

Shane Charles
Software Developer