You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The instances of Bifunctor and Biapply aren't as lazy as they could be for single-constructor types. For example, comparing (Control.Arrow.***) and Data.Bifunctor.bimap:
The problem with making this change is that the instances then violate the (bi)functor laws.
bimap f g | = (|, |) rather than |
I currently believe the irrefutable versions of these to be an anti-pattern as it causes us to duplicate a great deal of code to get things that aren't technically monads, functors, etc.
In practice I just find the irrefutable versions more useful. For example, I often write recursive functions that return tuples whose components should have lazy results, and they're much more convenient to write with e.g. bimap (x:) (y:) (recurse z) instead of manually pattern-matching (let ~(a,b) = recurse z in (x:a, y:b)).
If you want to stick to the theory that's fine, feel free to close this issue. Just pointing out something that'd allow me to use bifunctors instead of rolling my own tuple combinators (or using Control.Arrow for pairs) :-)
The instances of Bifunctor and Biapply aren't as lazy as they could be for single-constructor types. For example, comparing (Control.Arrow.***) and Data.Bifunctor.bimap:
The Bifunctor instances for the various tuple types and Const should be using irrefutable patterns. Likewise for the Biapply (,) instance.
The text was updated successfully, but these errors were encountered: