Fsharpplus: Implement tee/tap for functors?

Created on 18 Dec 2019  路  12Comments  路  Source: fsprojects/FSharpPlus

The generic iter takes a functor and an action to perform, and returns unit.

I'd like a similar function that passes through the functor, i.e. performs a unit-returning action and then returns the original input (for further chaining). As I understand it, this is typically called tee or tap. Could this be added?

Le me know if this is unclear and I should provide more details.

enhancement

Most helpful comment

@cmeeren Sorry about my poor explanation, here's a (hopefully) better attempt.

Result<'T,'U> (read 'T and 'U as variable types) is a bifunctor, as I can map a ('T -> 'A) and a ('U -> 'B) and get a "bimapped"version of it.

Now, Result<'T,unit> (unit or another fixed type) is not, because I can't map any function to the right side, I could only map a unit->unit function, otherwise I would end up with a different type.

All 12 comments

I think tee also called tap is a function with signature ('T->unit) -> 'T -> 'T.

So, it's not restricted to functors, but you could achieve the desired effect by doing map (tee f) functor.

And yes, it's something that should be added to this library. The first question is which name it should be?

I have always called it tee, but I don't really care whether it's called tee or tap. I may have come across another name, too, but I can't remember it at the moment.

Perhaps one could also define ftee or ftap as map >> tee, to have a similar function that works with inner functor values? Though AFAIK that would re-"construct" the functor, and a custom implementation that simply passes the whole functor through would be more effective (less allocations at the very least).

I've used entity.Tap(c=>...) in c#. I think in more functional f#y code I've seen some use of tee. Haskell seems to have both and use different semantics for them.

@wallymathieu I think tap is also used in Scala.

@cmeeren well, the composition is backwards map << tee but you're right in that it won't be efficient.

An easy alternative is let inline ftee f x = iter f x; x

Yep. Would be great to have that built-in, because defining such generic functions in our own projects causes compilation times and Intellisense lag to skyrocket.

A related thing to consider is an rftee or whatever you'd call it, that works on the "other" side of bifunctors (e.g. Result.Error or Choice2Of2).

I have even occasionally needed Option.teeNone (useful e.g. for easily logging warnings inside a pipeline when something should not be None), which could be viewed as rftee over Option if Option is a bifunctor where the right side is unit. But I suppose making Option such a bifunctor is stretching things a bit. 馃槤

let tee f x = f x; x

xs |> tee (iter (fun x -> ..))

?

@cannorin I think that snippet demonstrate that maybe ftee (or whichever name it gets) is not very justified, because it saves you only a few keystrokes. So maybe it doesn't worth poluting the lib with functions like this.

@cmeeren the problem is that Result<'t,unit> is not a bifunctor as you can't map any other type over unit.

I think we all agree tee / tap would make a good addition, as said before, we just have to agree on the name.

I personally like a bit more tap. Please cast your vote ;)

My personal preference is tap

@cmeeren the problem is that Result<'t,unit> is not a bifunctor as you can't map any other type over unit.

I'm no CT expert. Could you explain why Result<'t, unit> poses a problem (and for what)? I don't get it. unit is a type like any other, right?

@cmeeren Sorry about my poor explanation, here's a (hopefully) better attempt.

Result<'T,'U> (read 'T and 'U as variable types) is a bifunctor, as I can map a ('T -> 'A) and a ('U -> 'B) and get a "bimapped"version of it.

Now, Result<'T,unit> (unit or another fixed type) is not, because I can't map any function to the right side, I could only map a unit->unit function, otherwise I would end up with a different type.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TOTBWF picture TOTBWF  路  7Comments

cannorin picture cannorin  路  3Comments

cmeeren picture cmeeren  路  5Comments

cannorin picture cannorin  路  5Comments

cmeeren picture cmeeren  路  10Comments