Diagonalization/ dupe for monads and tuples?

It was pointed out to me in a private communication that the tuple function \x->(x,x) is actually a special case of a diagonalization for biapplicative and some related structures monadicially. Another example in the same flavor is pure impl for the applicative instance for sized lists. diag x = bipure x x So framed a litttle differently, there’s definitely an abstraction or common pattern lurking here. Perhaps folks can help Tease this out. One person I chatted with this morning alluded to it being relevant to computational flavors of adjunctions or some such ? It def matters in a different way when doing computation resource aware programming in a symmetric monoidal category. Let’s collect some ideas and patterns and get to the bottom of this!

We also have diag = join bipure and (in pseudo-Haskell) diag = unJoin . pure where newtype Join f a = Join { unJoin :: f a a } deriving (Functor) deriving instance Biapplicative f => Applicative (Join f) The latter seems on its face potentially related to the instance for lists of fixed length, but i am not sure how deep the connection may be.

Is the join bipure definition taking advantage of the (a->) monad
instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck
We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.

Nice! That's kind of what I was going for with Carter earlier in the day, thanks Matthew. I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`. Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities. Thoughts? Emily On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald < carter.schonwald@gmail.com > wrote:
Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck < strake888@ gmail. com ( strake888@gmail.com ) > wrote:
We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )

Whoops, I just realized I've been responding to Carter specifically instead of to the list. I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now. In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this: ``` class SymmetricMonoidal t i p => CartesianMonoidal t i p where duplicate :: p x (x `t` x) discard :: p x i -- Laws: -- duplicate >>> first discard = fwd lunit -- duplicate >>> second discard = fwd runit -- where -- lunit :: Monoidal t i p => Iso p x (i `t` x) -- runit :: Monoidal t i p => Iso p x (x `t` i) ``` i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure. This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)? On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald
mailto:carter.schonwald@gmail.com> wrote: Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck
mailto:strake888@gmail.com> wrote: We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.
_______________________________________________ Libraries mailing list Libraries@haskell.org mailto:Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

@Asad that's a perfectly reasonable way to think about diagonal operations: as the data of a cartesian monoidal category, and the laws are correct in this case. I think we can get away with the additional abstraction to `Biapplicative` in this case, though.
wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
Only if you chose that particular unit and that particular arrow. But there are other places where having a general `Biapplicative` contraint would make it useful. For example, i'd like to use this in `smash` with `diag :: a → Smash a a`, defining the adjoining of a point to `a` and creating a diagonal in the subcategory of pointed spaces in Hask, so that I don't have to redefine this as `diag' = quotSmash . view _CanIso . diag . Just`. Cheers, Emily On Wed, Sep 16, 2020 at 6:35 PM, Asad Saeeduddin < masaeedu@gmail.com > wrote:
Whoops, I just realized I've been responding to Carter specifically instead of to the list.
I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now.
In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p where duplicate :: p x (x `t` x) discard :: p x i
-- Laws: -- duplicate >>> first discard = fwd lunit -- duplicate >>> second discard = fwd runit
-- where -- lunit :: Monoidal t i p => Iso p x (i `t` x) -- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure.
This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald < carter. schonwald@ gmail. com ( carter.schonwald@gmail.com ) > wrote:
Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck < strake888@ gmail. com ( strake888@gmail.com ) > wrote:
We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )

Just to clarify, that's not the "real" diagonal in the space, but it is a super useful translation that I'd like for free :) On Wed, Sep 16, 2020 at 9:08 PM, Emily Pillmore < emilypi@cohomolo.gy > wrote:
@Asad that's a perfectly reasonable way to think about diagonal operations: as the data of a cartesian monoidal category, and the laws are correct in this case. I think we can get away with the additional abstraction to `Biapplicative` in this case, though.
wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
Only if you chose that particular unit and that particular arrow. But there are other places where having a general `Biapplicative` contraint would make it useful. For example, i'd like to use this in `smash` with `diag :: a → Smash a a`, defining the adjoining of a point to `a` and creating a diagonal in the subcategory of pointed spaces in Hask, so that I don't have to redefine this as `diag' = quotSmash . view _CanIso . diag . Just`.
Cheers,
Emily
On Wed, Sep 16, 2020 at 6:35 PM, Asad Saeeduddin < masaeedu@ gmail. com ( masaeedu@gmail.com ) > wrote:
Whoops, I just realized I've been responding to Carter specifically instead of to the list.
I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now.
In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p where duplicate :: p x (x `t` x) discard :: p x i
-- Laws: -- duplicate >>> first discard = fwd lunit -- duplicate >>> second discard = fwd runit
-- where -- lunit :: Monoidal t i p => Iso p x (i `t` x) -- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure.
This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald < carter. schonwald@ gmail. com ( carter.schonwald@gmail.com ) > wrote:
Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck < strake888@ gmail. com ( strake888@gmail.com ) > wrote:
We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )

For what it's worth, I'd just like to see a no-nonsense
dup : a -> (a,a)
dup a = (a,a)
in Data.Tuple, where it is out of the way, but right where you'd expect it
to be when looking for something for working with tuples.
Yes, bipure and id &&& id exist, and generalize it on two incompatible
axes, and if we had a proper cartesian category we'd be able to supply this
in full generality, as a morphism to the diagonal functor, but all of these
require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a
a -> a, which invites bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10 PM Emily Pillmore
Just to clarify, that's not the "real" diagonal in the space, but it is a super useful translation that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08 PM, Emily Pillmore
wrote: @Asad that's a perfectly reasonable way to think about diagonal operations: as the data of a cartesian monoidal category, and the laws are correct in this case. I think we can get away with the additional abstraction to `Biapplicative` in this case, though.
wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
Only if you chose that particular unit and that particular arrow. But there are other places where having a general `Biapplicative` contraint would make it useful. For example, i'd like to use this in `smash` with `diag :: a → Smash a a`, defining the adjoining of a point to `a` and creating a diagonal in the subcategory of pointed spaces in Hask, so that I don't have to redefine this as `diag' = quotSmash . view _CanIso . diag . Just`.
Cheers, Emily
On Wed, Sep 16, 2020 at 6:35 PM, Asad Saeeduddin
wrote: Whoops, I just realized I've been responding to Carter specifically instead of to the list.
I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now.
In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p
where
duplicate :: p x (x `t` x)
discard :: p x i
-- Laws:
-- duplicate >>> first discard = fwd lunit
-- duplicate >>> second discard = fwd runit
-- where
-- lunit :: Monoidal t i p => Iso p x (i `t` x)
-- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure.
This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)? On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald < carter.schonwald@gmail.com> wrote:
Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck < strake888@gmail.com> wrote:
We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing listLibraries@haskell.orghttp://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

`Either a a -> a` is another very handy operation. That and `a -> (a, a)` together make up 90% of use cases for `duplicate :: p x (t x x)`. On 9/17/20 12:49 AM, Edward Kmett wrote:
For what it's worth, I'd just like to see a no-nonsense
dup : a -> (a,a) dup a = (a,a)
in Data.Tuple, where it is out of the way, but right where you'd expect it to be when looking for something for working with tuples.
Yes, bipure and id &&& id exist, and generalize it on two incompatible axes, and if we had a proper cartesian category we'd be able to supply this in full generality, as a morphism to the diagonal functor, but all of these require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a a -> a, which invites bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10 PM Emily Pillmore
mailto:emilypi@cohomolo.gy> wrote: Just to clarify, that's not the "real" diagonal in the space, but it is a super useful translation that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08 PM, Emily Pillmore
mailto:emilypi@cohomolo.gy> wrote: @Asad that's a perfectly reasonable way to think about diagonal operations: as the data of a cartesian monoidal category, and the laws are correct in this case. I think we can get away with the additional abstraction to `Biapplicative` in this case, though.
wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
Only if you chose that particular unit and that particular arrow. But there are other places where having a general `Biapplicative` contraint would make it useful. For example, i'd like to use this in `smash` with `diag :: a → Smash a a`, defining the adjoining of a point to `a` and creating a diagonal in the subcategory of pointed spaces in Hask, so that I don't have to redefine this as `diag' = quotSmash . view _CanIso . diag . Just`.
Cheers, Emily
On Wed, Sep 16, 2020 at 6:35 PM, Asad Saeeduddin
mailto:masaeedu@gmail.com> wrote: Whoops, I just realized I've been responding to Carter specifically instead of to the list.
I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now.
In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p
where
duplicate :: p x (x `t` x)
discard :: p x i
-- Laws:
-- duplicate >>> first discard = fwd lunit
-- duplicate >>> second discard = fwd runit
-- where
-- lunit :: Monoidal t i p => Iso p x (i `t` x)
-- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure.
This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald
mailto:carter.schonwald@gmail.com> wrote: Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck
mailto:strake888@gmail.com> wrote: We also have
diag = join bipure
and (in pseudo-Haskell)
diag = unJoin . pure
where
newtype Join f a = Join { unJoin :: f a a } deriving (Functor)
deriving instance Biapplicative f => Applicative (Join f)
The latter seems on its face potentially related to the instance for
lists of fixed length, but i am not sure how deep the connection may
be.
_______________________________________________ Libraries mailing list Libraries@haskell.org mailto:Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org mailto:Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org mailto:Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org mailto:Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Proposing the following names then to start, and we can talk about expanding this at a later date: ``` -- In Data.Tuple diag :: a → (a,a) diag a = (a, a) -- In Data.Either codiag :: Either a a → a codiag = either id id ``` Thoughts? Emily On Thu, Sep 17, 2020 at 12:55 AM, Asad Saeeduddin < masaeedu@gmail.com > wrote:
`Either a a -> a` is another very handy operation. That and `a -> (a, a)` together make up 90% of use cases for `duplicate :: p x (t x x)`.
On 9/17/20 12:49 AM, Edward Kmett wrote:
For what it's worth, I'd just like to see a no-nonsense
dup : a -> (a,a) dup a = (a,a)
in Data.Tuple , where it is out of the way, but right where you'd expect it to be when looking for something for working with tuples.
Yes, bipure and id &&& id exist, and generalize it on two incompatible axes, and if we had a proper cartesian category we'd be able to supply this in full generality, as a morphism to the diagonal functor, but all of these require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a a -> a , which invites bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10 PM Emily Pillmore < emilypi@ cohomolo. gy ( emilypi@cohomolo.gy ) > wrote:
Just to clarify, that's not the "real" diagonal in the space, but it is a super useful translation that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08 PM, Emily Pillmore < emilypi@ cohomolo. gy ( emilypi@cohomolo.gy ) > wrote:
@Asad that's a perfectly reasonable way to think about diagonal operations: as the data of a cartesian monoidal category, and the laws are correct in this case. I think we can get away with the additional abstraction to `Biapplicative` in this case, though.
wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
Only if you chose that particular unit and that particular arrow. But there are other places where having a general `Biapplicative` contraint would make it useful. For example, i'd like to use this in `smash` with `diag :: a → Smash a a`, defining the adjoining of a point to `a` and creating a diagonal in the subcategory of pointed spaces in Hask, so that I don't have to redefine this as `diag' = quotSmash . view _CanIso . diag . Just`.
Cheers,
Emily
On Wed, Sep 16, 2020 at 6:35 PM, Asad Saeeduddin < masaeedu@ gmail. com ( masaeedu@gmail.com ) > wrote:
Whoops, I just realized I've been responding to Carter specifically instead of to the list.
I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now.
In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p where duplicate :: p x (x `t` x) discard :: p x i
-- Laws: -- duplicate >>> first discard = fwd lunit -- duplicate >>> second discard = fwd runit
-- where -- lunit :: Monoidal t i p => Iso p x (i `t` x) -- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure.
This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald < carter. schonwald@ gmail. com ( carter.schonwald@gmail.com ) > wrote:
> Is the join bipure definition taking advantage of the (a->) monad > instance? Slick! > > > > > On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck < strake888@ gmail. com > ( strake888@gmail.com ) > wrote: > > >> We also have >> >> >> >> diag = join bipure >> >> >> >> and (in pseudo-Haskell) >> >> >> >> diag = unJoin . pure >> >> where >> >> newtype Join f a = Join { unJoin :: f a a } deriving (Functor) >> >> deriving instance Biapplicative f => Applicative (Join f) >> >> >> >> The latter seems on its face potentially related to the instance for >> >> lists of fixed length, but i am not sure how deep the connection may >> >> be. >> >> > > > > > _______________________________________________ > Libraries mailing list > Libraries@ haskell. org ( Libraries@haskell.org ) > http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries ) > > >
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )
_______________________________________________ Libraries mailing list Libraries@ haskell. org ( Libraries@haskell.org ) http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries )

dup and dedup? Just throwing out names. Not sure I'm a fan of diag/coding.
On Thu, Sep 17, 2020, 00:10 Emily Pillmore
Proposing the following names then to start, and we can talk about expanding this at a later date:
``` -- In Data.Tuple diag :: a → (a,a) diag a = (a, a)
-- In Data.Either codiag :: Either a a → a codiag = either id id ```
Thoughts? Emily
On Thu, Sep 17, 2020 at 12:55 AM, Asad Saeeduddin
wrote: `Either a a -> a` is another very handy operation. That and `a -> (a, a)` together make up 90% of use cases for `duplicate :: p x (t x x)`. On 9/17/20 12:49 AM, Edward Kmett wrote:
For what it's worth, I'd just like to see a no-nonsense
dup : a -> (a,a) dup a = (a,a)
in Data.Tuple, where it is out of the way, but right where you'd expect it to be when looking for something for working with tuples.
Yes, bipure and id &&& id exist, and generalize it on two incompatible axes, and if we had a proper cartesian category we'd be able to supply this in full generality, as a morphism to the diagonal functor, but all of these require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a a -> a, which invites bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10 PM Emily Pillmore
wrote: Just to clarify, that's not the "real" diagonal in the space, but it is a super useful translation that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08 PM, Emily Pillmore
wrote: @Asad that's a perfectly reasonable way to think about diagonal operations: as the data of a cartesian monoidal category, and the laws are correct in this case. I think we can get away with the additional abstraction to `Biapplicative` in this case, though.
wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)?
Only if you chose that particular unit and that particular arrow. But there are other places where having a general `Biapplicative` contraint would make it useful. For example, i'd like to use this in `smash` with `diag :: a → Smash a a`, defining the adjoining of a point to `a` and creating a diagonal in the subcategory of pointed spaces in Hask, so that I don't have to redefine this as `diag' = quotSmash . view _CanIso . diag . Just`.
Cheers, Emily
On Wed, Sep 16, 2020 at 6:35 PM, Asad Saeeduddin
wrote: Whoops, I just realized I've been responding to Carter specifically instead of to the list.
I was having some trouble understanding the `unJoin` stuff but I read it a few more times and I think I understand it a little better now.
In my personal experience the "abstracted version" of `x -> (x, x)` I use most often looks like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p
where
duplicate :: p x (x `t` x)
discard :: p x i
-- Laws:
-- duplicate >>> first discard = fwd lunit
-- duplicate >>> second discard = fwd runit
-- where
-- lunit :: Monoidal t i p => Iso p x (i `t` x)
-- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate and discard to some symmetric monoidal structure gives us a cartesian monoidal structure.
This doesn't really seem to be relevant to what you folks are looking for, but it does bring up a question. If some `Bifunctor` `t` happens to form a monoidal structure on `->`, wouldn't the existence of appropriate `forall a. a -> t a a` and `forall a. x -> Unit t` functions pigeonhole it into being "the" cartesian monoidal structure on `->` (and thus naturally isomorphic to `(,)`)? On 9/16/20 5:26 PM, Emily Pillmore wrote:
Nice!
That's kind of what I was going for with Carter earlier in the day, thanks Matthew.
I think a diagonalization function and functor are both very sensible additions to `bifunctors` and `Data.Bifunctor`. The theory behind this is sound: The diagonalization functor Δ: Hask → Hask^Hask, forms the center of the adjoint triple `colim -| Δ -| lim : Hask → Hask^Hask`.
Certainly the function `diag :: a → (a,a)` is something I've seen written in several libraries, and should be included in `Data.Tuple` as a `base` function. The clear generalization of this function is `diag :: Biapplicative f ⇒ a → f a a`. I'm in favor of both existing in their separate capacities.
Thoughts?
Emily
On Wed, Sep 16, 2020 at 3:49 PM, Carter Schonwald < carter.schonwald@gmail.com> wrote:
Is the join bipure definition taking advantage of the (a->) monad instance? Slick!
On Wed, Sep 16, 2020 at 3:39 PM Matthew Farkas-Dyck < strake888@gmail.com> wrote:
> We also have > > > > diag = join bipure > > > > and (in pseudo-Haskell) > > > > diag = unJoin . pure > > where > > newtype Join f a = Join { unJoin :: f a a } deriving (Functor) > > deriving instance Biapplicative f => Applicative (Join f) > > > > The latter seems on its face potentially related to the instance for > > lists of fixed length, but i am not sure how deep the connection may > > be. > > _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing listLibraries@haskell.orghttp://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

For the tuple monomorphic one id probably ageee with Dan.
On Thu, Sep 17, 2020 at 1:13 AM chessai
dup and dedup? Just throwing out names. Not sure I'm a fan of diag/coding.
On Thu, Sep 17, 2020, 00:10 Emily Pillmore
wrote: Proposing the following names then to start, and we can talk about expanding this at a later date:
``` -- In Data.Tuple diag :: a → (a,a) diag a = (a, a)
-- In Data.Either codiag :: Either a a → a codiag = either id id ```
Thoughts? Emily
On Thu, Sep 17, 2020 at 12:55 AM, Asad Saeeduddin
wrote: `Either a a -> a` is another very handy operation. That and `a
-> (a, a)` together make up 90% of use cases for `duplicate ::
p x (t x x)`.
On 9/17/20 12:49 AM, Edward Kmett
wrote:
For what it's worth, I'd just like to see a
no-nonsense
dup : a -> (a,a)
dup a = (a,a)
in Data.Tuple, where it is
out of the way, but right where you'd expect it to be when
looking for something for working with tuples.
Yes, bipure and id &&& id exist, and
generalize it on two incompatible axes, and if we had a proper
cartesian category we'd be able to supply this in full
generality, as a morphism to the diagonal functor, but all of
these require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a a -> a, which invites
bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10
PM Emily Pillmore
wrote: Just to clarify, that's not the "real" diagonal
in the space, but it is a super useful translation
that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08
PM, Emily Pillmore
wrote:
@Asad that's a perfectly reasonable
way to think about diagonal
operations: as the data of a cartesian
monoidal category, and the laws are
correct in this case. I think we can
get away with the additional
abstraction to `Biapplicative` in this
case, though.
wouldn't
the existence of
appropriate
`forall a. a ->
t a a` and `forall
a. x -> Unit t`
functions
pigeonhole it into
being "the"
cartesian monoidal
structure on
`->` (and thus
naturally
isomorphic to
`(,)`)?
Only if you chose that particular
unit and that particular arrow. But
there are other places where having
a general `Biapplicative` contraint
would make it useful. For example,
i'd like to use this in `smash`
with `diag :: a → Smash a a`,
defining the adjoining of a point to
`a` and creating a diagonal in the
subcategory of pointed spaces in
Hask, so that I don't have to
redefine this as `diag' = quotSmash
. view _CanIso . diag . Just`.
Cheers,
Emily
On Wed, Sep 16,
2020 at 6:35 PM, Asad Saeeduddin
wrote:
Whoops, I just realized I've
been responding to Carter
specifically instead of to the
list.
I was having some trouble
understanding the `unJoin` stuff
but I read it a few more times
and I think I understand it a
little better now.
In my personal experience the
"abstracted version" of `x ->
(x, x)` I use most often looks
like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p
where
duplicate :: p x (x `t` x)
discard :: p x i
-- Laws:
-- duplicate >>> first discard = fwd lunit
-- duplicate >>> second discard = fwd runit
-- where
-- lunit :: Monoidal t i p => Iso p x (i `t` x)
-- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate
and discard to some symmetric
monoidal structure gives us a
cartesian monoidal structure.
This doesn't really seem to be
relevant to what you folks are
looking for, but it does bring
up a question. If some
`Bifunctor` `t` happens to form
a monoidal structure on `->`,
wouldn't the existence of
appropriate `forall a. a -> t
a a` and `forall a. x -> Unit
t` functions pigeonhole it into
being "the" cartesian monoidal
structure on `->` (and thus
naturally isomorphic to `(,)`)?
On 9/16/20 5:26 PM, Emily
Pillmore wrote:
Nice!
That's kind of what I
was going for with
Carter earlier in the
day, thanks Matthew.
I think a
diagonalization
function and functor
are both very sensible
additions to
`bifunctors` and
`Data.Bifunctor`. The
theory behind this is
sound: The
diagonalization
functor Δ: Hask →
Hask^Hask, forms the
center of the adjoint
triple `colim -| Δ -|
lim : Hask →
Hask^Hask`.
Certainly the function
`diag :: a → (a,a)` is
something I've seen
written in several
libraries, and should
be included in
`Data.Tuple` as a
`base` function. The
clear generalization
of this function is
`diag :: Biapplicative
f ⇒ a → f a a`. I'm in
favor of both existing
in their separate
capacities.
Thoughts?
Emily
On
Wed, Sep 16, 2020 at
3:49 PM, Carter
Schonwald
wrote:
> > > > > > Is > > the join bipure > > definition > > taking advantage > > of the (a->) > > monad instance? > > Slick! > > > > > > > > > > > > > > > > > On > > Wed, Sep 16, > > 2020 at 3:39 > > PM Matthew > > Farkas-Dyck > >
wrote: > > > > > We also have >> >> >> >> >> >> >> >> >> >> >> >> diag = join >> >> bipure >> >> >> >> >> >> >> >> >> >> >> >> and (in >> >> pseudo-Haskell) >> >> >> >> >> >> >> >> >> >> >> >> diag = unJoin >> >> . pure >> >> >> >> >> >> where >> >> >> >> >> >> newtype >> >> Join f a = >> >> Join { unJoin >> >> :: f a a } >> >> deriving >> >> (Functor) >> >> >> >> >> >> deriving >> >> instance >> >> Biapplicative >> >> f => >> >> Applicative >> >> (Join f) >> >> >> >> >> >> >> >> >> >> >> >> The latter >> >> seems on its >> >> face >> >> potentially >> >> related to the >> >> instance for >> >> >> >> >> >> lists of fixed >> >> length, but i >> >> am not sure >> >> how deep the >> >> connection may >> >> >> >> >> >> be. >> >> >> >> >> >> > > > > > > _______________________________________________ > > > > > Libraries > > mailing list > > > Libraries@haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > > _______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org

I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a
These names have precedent in several existing packages, and they’re
straightforward to explain in context: ‘dup’ is short for “duplicate” and
appears in other contexts like stack languages and (not coincidentally)
some category theory; ‘fromEither’ is the obvious thing missing from
________ : ‘either’ :: ‘fromMaybe’ : ‘maybe’.
(The only alternatives I would sincerely propose are ‘copy’ and ‘merge’,
but those are less specialised, and so less illustrative. Copy a file?
Merge two lists?)
I don’t feel that strongly about the names of the hypothetical
generalisations, and indeed it depends on which way(s) they get generalised.
I like ‘diag’ and ‘codiag’ well enough for categorical/arrow combinators,
as long as they’re *not* the names of the simplified/specialised versions.
On Wed, Sep 16, 2020, 10:20 PM Carter Schonwald
For the tuple monomorphic one id probably ageee with Dan.
On Thu, Sep 17, 2020 at 1:13 AM chessai
wrote: dup and dedup? Just throwing out names. Not sure I'm a fan of diag/coding.
On Thu, Sep 17, 2020, 00:10 Emily Pillmore
wrote: Proposing the following names then to start, and we can talk about expanding this at a later date:
``` -- In Data.Tuple diag :: a → (a,a) diag a = (a, a)
-- In Data.Either codiag :: Either a a → a codiag = either id id ```
Thoughts? Emily
On Thu, Sep 17, 2020 at 12:55 AM, Asad Saeeduddin
wrote: `Either a a -> a` is another very handy operation. That and `a
-> (a, a)` together make up 90% of use cases for `duplicate ::
p x (t x x)`.
On 9/17/20 12:49 AM, Edward Kmett
wrote:
For what it's worth, I'd just like to see a
no-nonsense
dup : a -> (a,a)
dup a = (a,a)
in Data.Tuple, where it is
out of the way, but right where you'd expect it to be when
looking for something for working with tuples.
Yes, bipure and id &&& id exist, and
generalize it on two incompatible axes, and if we had a proper
cartesian category we'd be able to supply this in full
generality, as a morphism to the diagonal functor, but all of
these require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a a -> a, which invites
bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10
PM Emily Pillmore
wrote: Just to clarify, that's not the "real" diagonal
in the space, but it is a super useful translation
that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08
PM, Emily Pillmore
wrote:
@Asad that's a perfectly reasonable
way to think about diagonal
operations: as the data of a cartesian
monoidal category, and the laws are
correct in this case. I think we can
get away with the additional
abstraction to `Biapplicative` in this
case, though.
wouldn't
the existence of
appropriate
`forall a. a ->
t a a` and `forall
a. x -> Unit t`
functions
pigeonhole it into
being "the"
cartesian monoidal
structure on
`->` (and thus
naturally
isomorphic to
`(,)`)?
Only if you chose that particular
unit and that particular arrow. But
there are other places where having
a general `Biapplicative` contraint
would make it useful. For example,
i'd like to use this in `smash`
with `diag :: a → Smash a a`,
defining the adjoining of a point to
`a` and creating a diagonal in the
subcategory of pointed spaces in
Hask, so that I don't have to
redefine this as `diag' = quotSmash
. view _CanIso . diag . Just`.
Cheers,
Emily
On Wed, Sep 16,
2020 at 6:35 PM, Asad Saeeduddin
wrote:
> > > > > > Whoops, I just realized I've > > been responding to Carter > > specifically instead of to the > > list. > > > > > > I was having some trouble > > understanding the `unJoin` stuff > > but I read it a few more times > > and I think I understand it a > > little better now. > > > > > > In my personal experience the > > "abstracted version" of `x -> > > (x, x)` I use most often looks > > like this: > > > > > > ``` > > > > > class SymmetricMonoidal t i p => CartesianMonoidal t i p > > > > where > > > > duplicate :: p x (x `t` x) > > > > discard :: p x i > > > > > > -- Laws: > > > > -- duplicate >>> first discard = fwd lunit > > > > -- duplicate >>> second discard = fwd runit > > > > > > -- where > > > > -- lunit :: Monoidal t i p => Iso p x (i `t` x) > > > > -- runit :: Monoidal t i p => Iso p x (x `t` i) > > > > ``` > > > > > > i.e. adding a suitable duplicate > > and discard to some symmetric > > monoidal structure gives us a > > cartesian monoidal structure. > > > > > > This doesn't really seem to be > > relevant to what you folks are > > looking for, but it does bring > > up a question. If some > > `Bifunctor` `t` happens to form > > a monoidal structure on `->`, > > wouldn't the existence of > > appropriate `forall a. a -> t > > a a` and `forall a. x -> Unit > > t` functions pigeonhole it into > > being "the" cartesian monoidal > > structure on `->` (and thus > > naturally isomorphic to `(,)`)? > > > On 9/16/20 5:26 PM, Emily > > Pillmore wrote: > > > > > > > > > > > > > > > Nice! > > > > > > That's kind of what I > > was going for with > > Carter earlier in the > > day, thanks Matthew. > > > > > > > > I think a > > diagonalization > > function and functor > > are both very sensible > > additions to > > `bifunctors` and > > `Data.Bifunctor`. The > > theory behind this is > > sound: The > > diagonalization > > functor Δ: Hask → > > Hask^Hask, forms the > > center of the adjoint > > triple `colim -| Δ -| > > lim : Hask → > > Hask^Hask`. > > > > > > Certainly the function > > `diag :: a → (a,a)` is > > something I've seen > > written in several > > libraries, and should > > be included in > > `Data.Tuple` as a > > `base` function. The > > clear generalization > > of this function is > > `diag :: Biapplicative > > f ⇒ a → f a a`. I'm in > > favor of both existing > > in their separate > > capacities. > > > > > > > > Thoughts? > > > > > > > > > > Emily > > > > > > > > > > > > > > > On > > Wed, Sep 16, 2020 at > > 3:49 PM, Carter > > Schonwald
> > wrote: > > > >> >> >> >> >> >> Is >> >> the join bipure >> >> definition >> >> taking advantage >> >> of the (a->) >> >> monad instance? >> >> Slick! >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> On >> >> Wed, Sep 16, >> >> 2020 at 3:39 >> >> PM Matthew >> >> Farkas-Dyck >> >> wrote: >> >> >> >> >> We also have >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> diag = join >>> >>> bipure >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> and (in >>> >>> pseudo-Haskell) >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> diag = unJoin >>> >>> . pure >>> >>> >>> >>> >>> >>> where >>> >>> >>> >>> >>> >>> newtype >>> >>> Join f a = >>> >>> Join { unJoin >>> >>> :: f a a } >>> >>> deriving >>> >>> (Functor) >>> >>> >>> >>> >>> >>> deriving >>> >>> instance >>> >>> Biapplicative >>> >>> f => >>> >>> Applicative >>> >>> (Join f) >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> The latter >>> >>> seems on its >>> >>> face >>> >>> potentially >>> >>> related to the >>> >>> instance for >>> >>> >>> >>> >>> >>> lists of fixed >>> >>> length, but i >>> >>> am not sure >>> >>> how deep the >>> >>> connection may >>> >>> >>> >>> >>> >>> be. >>> >>> >>> >>> >>> >>> >> >> >> >> >> >> _______________________________________________ >> >> >> >> >> Libraries >> >> mailing list >> >> >> Libraries@haskell.org >> >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> >> >> >> >> >> > > > > > > > > > > > > > > > > > > _______________________________________________ > > Libraries mailing list > > Libraries@haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > _______________________________________________ > > > > > Libraries mailing list > > > > > Libraries@haskell.org > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > > _______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach. On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a

I’d expect fromEither to be
Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a

You may wish to compare with fromMaybe then, which probably also doesn't have the type you'd expect :) The type you have there is more like bifoldMap On Thu, 17 Sep 2020, at 1:42 PM, Carter Schonwald wrote:
I’d expect fromEither to be Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
wrote: __ Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a

My instinct about fromEither's type was the same as Carter's, and I had to
remind myself of fromMaybe. I like the name fromEither overall. Seems to
fit well with precedent and is straightforward enough.
On Thu, Sep 17, 2020, 07:45 Oliver Charles
You may wish to compare with fromMaybe then, which probably also doesn't have the type you'd expect :) The type you have there is more like bifoldMap
On Thu, 17 Sep 2020, at 1:42 PM, Carter Schonwald wrote:
I’d expect fromEither to be Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
wrote: Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

I’m not sure how fromMaybe relates here. Could someone explain?
For the anti-categorical folks who dislike codiag or related names like
trace (in linear algebra trace is the sum of the diagonal of a matrix as a
scalar, an apt analogy I think), another name that I think is descriptive
is collapse
Names bandied about so far:
Dedup
Codiag
Fromeither
Things I mentioned above : trace and collapse
Zooming out though, this operation is equiv to “either id id”, so I don’t
really see how inventing a new name for this specific tiny snippet really
helps anyone.
On Thu, Sep 17, 2020 at 8:54 AM chessai
My instinct about fromEither's type was the same as Carter's, and I had to remind myself of fromMaybe. I like the name fromEither overall. Seems to fit well with precedent and is straightforward enough.
On Thu, Sep 17, 2020, 07:45 Oliver Charles
wrote: You may wish to compare with fromMaybe then, which probably also doesn't have the type you'd expect :) The type you have there is more like bifoldMap
On Thu, 17 Sep 2020, at 1:42 PM, Carter Schonwald wrote:
I’d expect fromEither to be Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
wrote: Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a
_______________________________________________
Libraries mailing list
Libraries@haskell.org

Hopping on the bikeshed, I've heard 'Either a a -> a' described as 'untagging' the 'a'. So from a less categorical perspective, I'd call it
+ 'untag' (already used in Data.Tagged)
+ or 'unEither' (because you're directly unwrapping the Either, not using a fallback value like 'fromMaybe').
Either of these should be more immediately clear than 'codiag', 'codup', or 'dedup', which would make more sense as (categorical) class methods.
--Keith
Sent from my phone with K-9 Mail.
On September 17, 2020 1:33:40 PM UTC, Carter Schonwald
I’m not sure how fromMaybe relates here. Could someone explain?
For the anti-categorical folks who dislike codiag or related names like trace (in linear algebra trace is the sum of the diagonal of a matrix as a scalar, an apt analogy I think), another name that I think is descriptive is collapse
Names bandied about so far:
Dedup Codiag Fromeither
Things I mentioned above : trace and collapse
Zooming out though, this operation is equiv to “either id id”, so I don’t really see how inventing a new name for this specific tiny snippet really helps anyone.
On Thu, Sep 17, 2020 at 8:54 AM chessai
wrote: My instinct about fromEither's type was the same as Carter's, and I had to remind myself of fromMaybe. I like the name fromEither overall. Seems to fit well with precedent and is straightforward enough.
On Thu, Sep 17, 2020, 07:45 Oliver Charles
wrote: You may wish to compare with fromMaybe then, which probably also doesn't have the type you'd expect :) The type you have there is more like bifoldMap
On Thu, 17 Sep 2020, at 1:42 PM, Carter Schonwald wrote:
I’d expect fromEither to be Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
wrote: Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a
_______________________________________________
Libraries mailing list
Libraries@haskell.org

{ fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … }
extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable
default if “it” isn’t present.
These functions map a type onto the smallest product type that can
represent the union of its possible values, taking defaults as needed to
make the result total. They seem asymmetric at first glance because the
structures of the input types differ, but they’re all doing the same thing.
More to the point, anecdotally, I see Haskell beginners often reaching for
accessor functions like ‘head’ and ‘fromJust’ before they’ve internalised
pattern matching. They do use total combinators like ‘fromMaybe’ if
available (and if they’re aware of them), because these combinators are
more convenient than ‘if isJust … then fromJust … else …’, and they only
happen to be safer incidentally. It’s the familiar “get value or default”
pattern, if they’ve programmed before, nothing to do with totality. So it
seems sensible to me to plug the hole in the taxonomy.
On Thu, Sep 17, 2020, 6:34 AM Carter Schonwald
I’m not sure how fromMaybe relates here. Could someone explain?
For the anti-categorical folks who dislike codiag or related names like trace (in linear algebra trace is the sum of the diagonal of a matrix as a scalar, an apt analogy I think), another name that I think is descriptive is collapse
Names bandied about so far:
Dedup Codiag Fromeither
Things I mentioned above : trace and collapse
Zooming out though, this operation is equiv to “either id id”, so I don’t really see how inventing a new name for this specific tiny snippet really helps anyone.
On Thu, Sep 17, 2020 at 8:54 AM chessai
wrote: My instinct about fromEither's type was the same as Carter's, and I had to remind myself of fromMaybe. I like the name fromEither overall. Seems to fit well with precedent and is straightforward enough.
On Thu, Sep 17, 2020, 07:45 Oliver Charles
wrote: You may wish to compare with fromMaybe then, which probably also doesn't have the type you'd expect :) The type you have there is more like bifoldMap
On Thu, 17 Sep 2020, at 1:42 PM, Carter Schonwald wrote:
I’d expect fromEither to be Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
wrote: Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Makes sense to me!
On Thu, Sep 17, 2020, 12:59 PM Jon Purdy
{ fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.
These functions map a type onto the smallest product type that can represent the union of its possible values, taking defaults as needed to make the result total. They seem asymmetric at first glance because the structures of the input types differ, but they’re all doing the same thing.
More to the point, anecdotally, I see Haskell beginners often reaching for accessor functions like ‘head’ and ‘fromJust’ before they’ve internalised pattern matching. They do use total combinators like ‘fromMaybe’ if available (and if they’re aware of them), because these combinators are more convenient than ‘if isJust … then fromJust … else …’, and they only happen to be safer incidentally. It’s the familiar “get value or default” pattern, if they’ve programmed before, nothing to do with totality. So it seems sensible to me to plug the hole in the taxonomy.
On Thu, Sep 17, 2020, 6:34 AM Carter Schonwald
wrote: I’m not sure how fromMaybe relates here. Could someone explain?
For the anti-categorical folks who dislike codiag or related names like trace (in linear algebra trace is the sum of the diagonal of a matrix as a scalar, an apt analogy I think), another name that I think is descriptive is collapse
Names bandied about so far:
Dedup Codiag Fromeither
Things I mentioned above : trace and collapse
Zooming out though, this operation is equiv to “either id id”, so I don’t really see how inventing a new name for this specific tiny snippet really helps anyone.
On Thu, Sep 17, 2020 at 8:54 AM chessai
wrote: My instinct about fromEither's type was the same as Carter's, and I had to remind myself of fromMaybe. I like the name fromEither overall. Seems to fit well with precedent and is straightforward enough.
On Thu, Sep 17, 2020, 07:45 Oliver Charles
wrote: You may wish to compare with fromMaybe then, which probably also doesn't have the type you'd expect :) The type you have there is more like bifoldMap
On Thu, 17 Sep 2020, at 1:42 PM, Carter Schonwald wrote:
I’d expect fromEither to be Either a b -> (a-> c )-> (b-> c) -> c
Nothing about the name fromEither is suggestive of the Either a a type
On Thu, Sep 17, 2020 at 3:45 AM Oliver Charles
wrote: Regardless of having a more abstract version, I'm +1 on Jon's suggestion, and those names. fromEither is something I have reached for many many times and been surprised it's not within arms reach.
On Thu, 17 Sep 2020, at 7:16 AM, Jon Purdy wrote:
I’m strongly for these:
Data.Tuple.dup :: a → (a, a)
Data.Either.fromEither :: Either a a → a
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy
{ fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.
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`. This maybe isn't a big deal. Just seemed worth noting.

TL;DR: maybe we can think of this as combining disjoint empty & non-empty cases of folds. Every time I’ve wanted to define something like this I’ve found myself dissatisfied because of this asymmetry. 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: foldr1OrDefault :: Foldable t => (a -> a -> a) -> a -> t a -> a foldr1OrDefault f z t | null t = z | otherwise = foldr1 f t 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. 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: fold1Maybe :: (Foldable t, Semigroup a) => t a -> Maybe a fold1Maybe = foldMap Just fold1OrDefault :: (Foldable t, Semigroup a) => a -> t a -> a fold1OrDefault z = fromMaybe z . foldMap Just (All of these names are intentionally bad because I don’t want to propose adding these functions anywhere just yet.) 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: fromEither :: (b -> a) -> Either b a -> a fromEither f = either f id 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). 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? Rob
On Sep 17, 2020, at 1:13 PM, Philip Hazelden
wrote: On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy
mailto:evincarofautumn@gmail.com> wrote: { fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present. 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`.
This maybe isn't a big deal. Just seemed worth noting. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Rob,
1) your foldEither is way better and I love it.
2) this is a way more pleasing Avenue of design for the tuple and either
combinators ! Thank you for sharing this great little exposition.
On Wed, Sep 23, 2020 at 8:20 AM Rob Rix via Libraries
TL;DR: maybe we can think of this as combining disjoint empty & non-empty cases of folds.
Every time I’ve wanted to define something like this I’ve found myself dissatisfied because of this asymmetry.
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:
foldr1OrDefault :: Foldable t => (a -> a -> a) -> a -> t a -> a foldr1OrDefault f z t | null t = z | otherwise = foldr1 f t
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.
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:
fold1Maybe :: (Foldable t, Semigroup a) => t a -> Maybe a fold1Maybe = foldMap Just
fold1OrDefault :: (Foldable t, Semigroup a) => a -> t a -> a fold1OrDefault z = fromMaybe z . foldMap Just
(All of these names are intentionally bad because I don’t want to propose adding these functions anywhere just yet.)
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:
fromEither :: (b -> a) -> Either b a -> a fromEither f = either f id
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).
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?
Rob
On Sep 17, 2020, at 1:13 PM, Philip Hazelden
wrote: On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy
wrote: { fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.
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`.
This maybe isn't a big deal. Just seemed worth noting.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
Libraries@haskell.org

How about `eitherId` for the `Either a a -> a`? I.e one usually does
`either id id` to extract either value.
`fromEither` isn't a bad idea, but it's long.
On Wed, Sep 23, 2020 at 3:49 PM Carter Schonwald
Rob, 1) your foldEither is way better and I love it.
2) this is a way more pleasing Avenue of design for the tuple and either combinators ! Thank you for sharing this great little exposition.
On Wed, Sep 23, 2020 at 8:20 AM Rob Rix via Libraries < libraries@haskell.org> wrote:
TL;DR: maybe we can think of this as combining disjoint empty & non-empty cases of folds.
Every time I’ve wanted to define something like this I’ve found myself dissatisfied because of this asymmetry.
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:
foldr1OrDefault :: Foldable t => (a -> a -> a) -> a -> t a -> a foldr1OrDefault f z t | null t = z | otherwise = foldr1 f t
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.
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:
fold1Maybe :: (Foldable t, Semigroup a) => t a -> Maybe a fold1Maybe = foldMap Just
fold1OrDefault :: (Foldable t, Semigroup a) => a -> t a -> a fold1OrDefault z = fromMaybe z . foldMap Just
(All of these names are intentionally bad because I don’t want to propose adding these functions anywhere just yet.)
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:
fromEither :: (b -> a) -> Either b a -> a fromEither f = either f id
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).
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?
Rob
On Sep 17, 2020, at 1:13 PM, Philip Hazelden
wrote: On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy
wrote: { fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.
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`.
This maybe isn't a big deal. Just seemed worth noting.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
-- Markus Läll

I support adding both
a -> (a,a)
and
Either a a -> a
dedup doesn't seem right to me because there aren't two things, so I
submit the name: whichever.
whichever :: Either a a -> a
Just give me whichever one's there.
When I see the name fromEither, I think of the type
(e -> a) -> Either e a -> a
so I am against the name fromEither being used for Either a a -> a
I'm not fully satisfied by either pair of diag,codiag / dup,dedup
but I could live with them.
My preference is dup/whichever
Cheers,
George
On Fri, 25 Sep 2020 at 22:56, Markus Läll
How about `eitherId` for the `Either a a -> a`? I.e one usually does `either id id` to extract either value.
`fromEither` isn't a bad idea, but it's long.
On Wed, Sep 23, 2020 at 3:49 PM Carter Schonwald
wrote: Rob, 1) your foldEither is way better and I love it.
2) this is a way more pleasing Avenue of design for the tuple and either combinators ! Thank you for sharing this great little exposition.
On Wed, Sep 23, 2020 at 8:20 AM Rob Rix via Libraries
wrote: TL;DR: maybe we can think of this as combining disjoint empty & non-empty cases of folds.
Every time I’ve wanted to define something like this I’ve found myself dissatisfied because of this asymmetry.
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:
foldr1OrDefault :: Foldable t => (a -> a -> a) -> a -> t a -> a foldr1OrDefault f z t | null t = z | otherwise = foldr1 f t
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.
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:
fold1Maybe :: (Foldable t, Semigroup a) => t a -> Maybe a fold1Maybe = foldMap Just
fold1OrDefault :: (Foldable t, Semigroup a) => a -> t a -> a fold1OrDefault z = fromMaybe z . foldMap Just
(All of these names are intentionally bad because I don’t want to propose adding these functions anywhere just yet.)
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:
fromEither :: (b -> a) -> Either b a -> a fromEither f = either f id
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).
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?
Rob
On Sep 17, 2020, at 1:13 PM, Philip Hazelden
wrote: On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy
wrote: { fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.
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`.
This maybe isn't a big deal. Just seemed worth noting.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
-- Markus Läll _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Dup and whichever for the tuple and either sound fine, as long as there’s
a reference to diag and codiag or whatever names we settle on for the
general versions that are the actual subject of this thread.
I’d genuinely appreciate it if folks actually address or think about the
generalizations that are the start of this thread please! :)
On Sat, Sep 26, 2020 at 2:55 AM George Wilson
I support adding both
a -> (a,a)
and
Either a a -> a
dedup doesn't seem right to me because there aren't two things, so I
submit the name: whichever.
whichever :: Either a a -> a
Just give me whichever one's there.
When I see the name fromEither, I think of the type
(e -> a) -> Either e a -> a
so I am against the name fromEither being used for Either a a -> a
I'm not fully satisfied by either pair of diag,codiag / dup,dedup
but I could live with them.
My preference is dup/whichever
Cheers,
George
On Fri, 25 Sep 2020 at 22:56, Markus Läll
wrote: How about `eitherId` for the `Either a a -> a`? I.e one usually does `either id id` to extract either value.
`fromEither` isn't a bad idea, but it's long.
On Wed, Sep 23, 2020 at 3:49 PM Carter Schonwald < carter.schonwald@gmail.com> wrote:
Rob,
1) your foldEither is way better and I love it.
2) this is a way more pleasing Avenue of design for the tuple and either combinators ! Thank you for sharing this great little exposition.
On Wed, Sep 23, 2020 at 8:20 AM Rob Rix via Libraries < libraries@haskell.org> wrote:
TL;DR: maybe we can think of this as combining disjoint empty & non-empty cases of folds.
Every time I’ve wanted to define something like this I’ve found myself dissatisfied because of this asymmetry.
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:
foldr1OrDefault :: Foldable t => (a -> a -> a) -> a -> t a -> a
foldr1OrDefault f z t
| null t = z
| otherwise = foldr1 f t
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.
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:
fold1Maybe :: (Foldable t, Semigroup a) => t a -> Maybe a
fold1Maybe = foldMap Just
fold1OrDefault :: (Foldable t, Semigroup a) => a -> t a -> a
fold1OrDefault z = fromMaybe z . foldMap Just
(All of these names are intentionally bad because I don’t want to propose adding these functions anywhere just yet.)
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:
fromEither :: (b -> a) -> Either b a -> a
fromEither f = either f id
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).
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?
Rob
On Sep 17, 2020, at 1:13 PM, Philip Hazelden < philip.hazelden@gmail.com> wrote:
On Thu, Sep 17, 2020 at 5:59 PM Jon Purdy
wrote: { fromMaybe, fromLeft, fromRight, fromEither, fromThese, fromDynamic, … } extracts “the” value out of a { Maybe, These, Dynamic, … } with a suitable default if “it” isn’t present.
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`.
This maybe isn't a big deal. Just seemed worth noting.
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
--
Markus Läll
_______________________________________________
Libraries mailing list
Libraries@haskell.org

On Thu, Sep 17, 2020 at 08:44:45AM +0100, Oliver Charles wrote:
[...] fromEither is something I have reached for many many times and been surprised it's not within arms reach.
Would you mind, just out of curiosity, explaining what types of situations you've found yourself wanting an `Either a a -> a` function? Tom

Out of curiosity what have been your uses for symmetric monoidal categories?
Few things I’d like to remark upon :
1) in many models that are monoidal braided categories , Eg full linear
logic, there’s at least two sum types and two product types.
2) in my own experience in that setting, at least for modelling
authorization, I wind up wanting dup to take an evidence argument, which
leads to duplicate With proof being in its own class and the proof term
being an associated type / fun dep wrt the thing we duplicate.
Eg dup:: DupProof a p => a-> p-> (a,a)
(And in fact something like this is needed to enable njce desugaring for
pattern matching guard computations for stuff like linear Haskell I think.
3) the in practice dual for duplicate with evidence seems to be more like
use :: UseProof a p => (a,p) -> (), at least in general and ignoring a
bunch of nuances that can lead to different choices in signatures
On Thu, Sep 17, 2020 at 12:56 AM Asad Saeeduddin
`Either a a -> a` is another very handy operation. That and `a
-> (a, a)` together make up 90% of use cases for `duplicate ::
p x (t x x)`.
On 9/17/20 12:49 AM, Edward Kmett
wrote:
For what it's worth, I'd just like to see a
no-nonsense
dup : a -> (a,a)
dup a = (a,a)
in Data.Tuple, where it is
out of the way, but right where you'd expect it to be when
looking for something for working with tuples.
Yes, bipure and id &&& id exist, and
generalize it on two incompatible axes, and if we had a proper
cartesian category we'd be able to supply this in full
generality, as a morphism to the diagonal functor, but all of
these require a level of rocket science to figure out.
I'd also happily support adding the equivalent in Data.Either for Either a a -> a, which invites
bikeshedding names.
-Edward
On Wed, Sep 16, 2020 at 6:10
PM Emily Pillmore
wrote: Just to clarify, that's not the "real" diagonal
in the space, but it is a super useful translation
that I'd like for free :)
On Wed, Sep 16, 2020 at 9:08
PM, Emily Pillmore
wrote:
@Asad that's a perfectly reasonable
way to think about diagonal
operations: as the data of a cartesian
monoidal category, and the laws are
correct in this case. I think we can
get away with the additional
abstraction to `Biapplicative` in this
case, though.
wouldn't
the existence of
appropriate
`forall a. a ->
t a a` and `forall
a. x -> Unit t`
functions
pigeonhole it into
being "the"
cartesian monoidal
structure on
`->` (and thus
naturally
isomorphic to
`(,)`)?
Only if you chose that particular
unit and that particular arrow. But
there are other places where having
a general `Biapplicative` contraint
would make it useful. For example,
i'd like to use this in `smash`
with `diag :: a → Smash a a`,
defining the adjoining of a point to
`a` and creating a diagonal in the
subcategory of pointed spaces in
Hask, so that I don't have to
redefine this as `diag' = quotSmash
. view _CanIso . diag . Just`.
Cheers,
Emily
On Wed, Sep 16,
2020 at 6:35 PM, Asad Saeeduddin
wrote:
Whoops, I just realized I've
been responding to Carter
specifically instead of to the
list.
I was having some trouble
understanding the `unJoin` stuff
but I read it a few more times
and I think I understand it a
little better now.
In my personal experience the
"abstracted version" of `x ->
(x, x)` I use most often looks
like this:
```
class SymmetricMonoidal t i p => CartesianMonoidal t i p
where
duplicate :: p x (x `t` x)
discard :: p x i
-- Laws:
-- duplicate >>> first discard = fwd lunit
-- duplicate >>> second discard = fwd runit
-- where
-- lunit :: Monoidal t i p => Iso p x (i `t` x)
-- runit :: Monoidal t i p => Iso p x (x `t` i)
```
i.e. adding a suitable duplicate
and discard to some symmetric
monoidal structure gives us a
cartesian monoidal structure.
This doesn't really seem to be
relevant to what you folks are
looking for, but it does bring
up a question. If some
`Bifunctor` `t` happens to form
a monoidal structure on `->`,
wouldn't the existence of
appropriate `forall a. a -> t
a a` and `forall a. x -> Unit
t` functions pigeonhole it into
being "the" cartesian monoidal
structure on `->` (and thus
naturally isomorphic to `(,)`)?
On 9/16/20 5:26 PM, Emily
Pillmore wrote:
Nice!
That's kind of what I
was going for with
Carter earlier in the
day, thanks Matthew.
I think a
diagonalization
function and functor
are both very sensible
additions to
`bifunctors` and
`Data.Bifunctor`. The
theory behind this is
sound: The
diagonalization
functor Δ: Hask →
Hask^Hask, forms the
center of the adjoint
triple `colim -| Δ -|
lim : Hask →
Hask^Hask`.
Certainly the function
`diag :: a → (a,a)` is
something I've seen
written in several
libraries, and should
be included in
`Data.Tuple` as a
`base` function. The
clear generalization
of this function is
`diag :: Biapplicative
f ⇒ a → f a a`. I'm in
favor of both existing
in their separate
capacities.
Thoughts?
Emily
On
Wed, Sep 16, 2020 at
3:49 PM, Carter
Schonwald
wrote:
Is
the join bipure
definition
taking advantage
of the (a->)
monad instance?
Slick!
On
Wed, Sep 16,
2020 at 3:39
PM Matthew
Farkas-Dyck
wrote: We also have
diag = join
bipure
and (in
pseudo-Haskell)
diag = unJoin
. pure
where
newtype
Join f a =
Join { unJoin
:: f a a }
deriving
(Functor)
deriving
instance
Biapplicative
f =>
Applicative
(Join f)
The latter
seems on its
face
potentially
related to the
instance for
lists of fixed
length, but i
am not sure
how deep the
connection may
be.
_______________________________________________
Libraries
mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org
_______________________________________________
Libraries mailing list
Libraries@haskell.org

Am 17.09.20 um 06:49 schrieb Edward Kmett:
For what it's worth, I'd just like to see a no-nonsense
dup : a -> (a,a) dup a = (a,a)
in Data.Tuple, where it is out of the way, but right where you'd expect it to be when looking for something for working with tuples.
Yes, bipure and id &&& id exist, and generalize it on two incompatible axes, and if we had a proper cartesian category we'd be able to supply this in full generality, as a morphism to the diagonal functor, but all of these require a level of rocket science to figure out.
+1 Cheers Ben

Does dup come with trip, quadrup, etc.? It doesn't have to, but once you
plug one hole the others nearby start to stand out.
On Wed, Sep 16, 2020, 1:58 PM Carter Schonwald
It was pointed out to me in a private communication that the tuple function \x->(x,x) is actually a special case of a diagonalization for biapplicative and some related structures monadicially. Another example in the same flavor is pure impl for the applicative instance for sized lists.
diag x = bipure x x
So framed a litttle differently, there’s definitely an abstraction or common pattern lurking here. Perhaps folks can help Tease this out. One person I chatted with this morning alluded to it being relevant to computational flavors of adjunctions or some such ? It def matters in a different way when doing computation resource aware programming in a symmetric monoidal category.
Let’s collect some ideas and patterns and get to the bottom of this! _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

My understanding was that the root was intended to mean 'duplicate', not
the number two, so if we did have those, I would expect them to be named
dup, dup3, dup4, etc.
On Thu, Sep 17, 2020, 12:03 David Feuer
Does dup come with trip, quadrup, etc.? It doesn't have to, but once you plug one hole the others nearby start to stand out.
On Wed, Sep 16, 2020, 1:58 PM Carter Schonwald
wrote: It was pointed out to me in a private communication that the tuple function \x->(x,x) is actually a special case of a diagonalization for biapplicative and some related structures monadicially. Another example in the same flavor is pure impl for the applicative instance for sized lists.
diag x = bipure x x
So framed a litttle differently, there’s definitely an abstraction or common pattern lurking here. Perhaps folks can help Tease this out. One person I chatted with this morning alluded to it being relevant to computational flavors of adjunctions or some such ? It def matters in a different way when doing computation resource aware programming in a symmetric monoidal category.
Let’s collect some ideas and patterns and get to the bottom of this! _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

*noun*
/ˈd(y)o͞opləkət/
1. 1.
one of two or more identical things.
"books may be disposed of if they are duplicates"
2. 2.
short for duplicate bridge.
3.
*verb*
/ˈd(y)o͞opləˌkāt/
1. make or be an exact copy of.
"they have not been able to duplicate his successes"
duplicate is a verb which means to make a copy of something. this is the
definition I have in mind when I see
dup :: a -> (a, a)
Of course the root of duplicate itself means two, but duplicate the verb
does not mean two.
Anyway, I'm not really interested in having more than 3 or 4, since that's
where you should have a datatype. And my interest for 3 and 4 is already
very low.
On Thu, Sep 17, 2020, 15:29 Matthew Farkas-Dyck
On 9/17/20, chessai
wrote: to mean 'duplicate', not the number two
'duplicate' means 2.

On 9/17/20, chessai
Of course the root of duplicate itself means two
Ah, i thought that's what you meant by your message about "the root". I've known "duplicate" to mean 2 copies, "triplicate" to mean 3, etc, and would mildly prefer `trip` over `dup3`, etc. That said, i'm not much inclined to have cases beyond 2 in base, anyhow ☺

I’m inclined against anything to do with higher tuples than pairs,
honestly. If there’s a real demand for it at some point, we can certainly
consider it, but pairs are vastly more common, and I’ve only ever wanted or
seen people wanting the ‘a → (a, a)’ version in practice.
Generally speaking, I see ≥3-tuples as a sign of a missing data type, and I
think I’m in likeminded company here.
If I really had my way, we’d make (,) a right-associative operator in both
values and types, so (a, b, c) = (a, (b, c)), and accessor functions could
work on any size of tuple.
I would also expect these functions to be called dup, dup3, dup4, &c. by
analogy with other tuple functions using that convention (e.g. zip, zip3).
On Thu, Sep 17, 2020, 10:03 AM David Feuer
Does dup come with trip, quadrup, etc.? It doesn't have to, but once you plug one hole the others nearby start to stand out.
On Wed, Sep 16, 2020, 1:58 PM Carter Schonwald
wrote: It was pointed out to me in a private communication that the tuple function \x->(x,x) is actually a special case of a diagonalization for biapplicative and some related structures monadicially. Another example in the same flavor is pure impl for the applicative instance for sized lists.
diag x = bipure x x
So framed a litttle differently, there’s definitely an abstraction or common pattern lurking here. Perhaps folks can help Tease this out. One person I chatted with this morning alluded to it being relevant to computational flavors of adjunctions or some such ? It def matters in a different way when doing computation resource aware programming in a symmetric monoidal category.
Let’s collect some ideas and patterns and get to the bottom of this! _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

If I really had my way, we’d make (,) a right-associative operator in both values and types, so (a, b, c) = (a, (b, c)), and accessor functions could work on any size of tuple.
uncurry . uncurry :: (a -> b -> c -> d) -> ((a, b), c) → d, so left-nesting may be more convenient.
—
Sent from my phone with K-9 Mail.
On September 17, 2020 5:20:04 PM UTC, Jon Purdy
I’m inclined against anything to do with higher tuples than pairs, honestly. If there’s a real demand for it at some point, we can certainly consider it, but pairs are vastly more common, and I’ve only ever wanted or seen people wanting the ‘a → (a, a)’ version in practice.
Generally speaking, I see ≥3-tuples as a sign of a missing data type, and I think I’m in likeminded company here.
If I really had my way, we’d make (,) a right-associative operator in both values and types, so (a, b, c) = (a, (b, c)), and accessor functions could work on any size of tuple.
I would also expect these functions to be called dup, dup3, dup4, &c. by analogy with other tuple functions using that convention (e.g. zip, zip3).
On Thu, Sep 17, 2020, 10:03 AM David Feuer
wrote: Does dup come with trip, quadrup, etc.? It doesn't have to, but once you plug one hole the others nearby start to stand out.
On Wed, Sep 16, 2020, 1:58 PM Carter Schonwald
wrote: It was pointed out to me in a private communication that the tuple function \x->(x,x) is actually a special case of a diagonalization for biapplicative and some related structures monadicially. Another example in the same flavor is pure impl for the applicative instance for sized lists.
diag x = bipure x x
So framed a litttle differently, there’s definitely an abstraction or common pattern lurking here. Perhaps folks can help Tease this out. One person I chatted with this morning alluded to it being relevant to computational flavors of adjunctions or some such ? It def matters in a different way when doing computation resource aware programming in a symmetric monoidal category.
Let’s collect some ideas and patterns and get to the bottom of this! _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
participants (18)
-
amindfv@mailbox.org
-
Asad Saeeduddin
-
Ben Franksen
-
Carter Schonwald
-
chessai
-
David Feuer
-
Edward Kmett
-
Emily Pillmore
-
George Wilson
-
Georgi Lyubenov
-
Henning Thielemann
-
Jon Purdy
-
Keith
-
Markus Läll
-
Matthew Farkas-Dyck
-
Oliver Charles
-
Philip Hazelden
-
Rob Rix