<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">TL;DR: maybe we can think of this as combining disjoint empty & non-empty cases of folds.</span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""><br class=""></span></div>Every time I’ve wanted to define something like this I’ve found myself dissatisfied because of this asymmetry.<div class=""><br class=""></div><div class="">Looking at it from another angle, I frequently encounter a vaguely similar situation with folds: given some collection which can be empty or non-, I want to fold over it with a function if non-empty, or return a default value if empty:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">foldr1OrDefault :: Foldable t => (a -> a -> a) -> a -> t a -> a</div><div class="">foldr1OrDefault f z t</div><div class=""> | null t = z</div><div class=""> | otherwise = foldr1 f t</div></blockquote><div class=""><br class=""></div><div class="">This is a bit like Control.Lens.Fold.foldBy in lens, except that the combining function f does not receive z at any point. Quite useful when you have a Semigroup but not a Monoid, or when you otherwise want to treat the empty case specially.</div><div class=""><br class=""></div><div class="">fromMaybe is a special case of this function, without the conceit of pretending that Maybe can hold multiple values. I’ve sometimes involved Maybe in this construction for just that reason when e.g. a is a Semigroup:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">fold1Maybe :: (Foldable t, Semigroup a) => t a -> Maybe a</div><div class="">fold1Maybe = foldMap Just</div><div class=""><br class=""></div><div class="">fold1OrDefault :: (Foldable t, Semigroup a) => a -> t a -> a</div><div class="">fold1OrDefault z = fromMaybe z . foldMap Just</div></blockquote><div class=""><br class=""></div><div class="">(All of these names are intentionally bad because I don’t want to propose adding these functions anywhere just yet.)</div><div class=""><br class=""></div><div class="">For Either (and These for that matter), a full generalization also has to deal with the extra information in the null case, i.e. Either b a would need (b -> a) instead of a:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">fromEither :: (b -> a) -> Either b a -> a</div><div class="">fromEither f = either f id</div></blockquote><div class=""><br class=""></div><div class="">I’m surprised about once every six months that this doesn’t exist (and then surprised again when consulting the types that fromLeft/fromRight aren’t either this *or* analogous to fromJust).</div><div class=""><br class=""></div><div class="">All of which is to say, I think I would prefer to have the generality of this fromEither to the a -> Either a a -> a version, but it’d be nice to figure out a way to see it as a fold, too. Maybe the Bifoldable1 instance for Either has something to contribute here?</div><div class=""><br class=""></div><div class="">Rob</div><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Sep 17, 2020, at 1:13 PM, Philip Hazelden <<a href="mailto:philip.hazelden@gmail.com" class="">philip.hazelden@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div dir="ltr" class="">On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy <<a href="mailto:evincarofautumn@gmail.com" class="">evincarofautumn@gmail.com</a>> wrote:<br class=""></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto" class="">{ fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.</div></blockquote><div class=""> </div><div class="">Hm. A weird thing about fromEither compared to (I think) all the rest of these, is that the type of the Either isn't fully general. That is, fromLeft and fromRight take an `Either a b`; fromThese takes a `These a b`. But the proposed `fromEither` takes an `Either a a`.</div><div class=""><br class=""></div><div class="">This maybe isn't a big deal. Just seemed worth noting.</div></div></div>
_______________________________________________<br class="">Libraries mailing list<br class=""><a href="mailto:Libraries@haskell.org" class="">Libraries@haskell.org</a><br class="">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries<br class=""></div></blockquote></div><br class=""></div></body></html>