Proposal: Add singleton function to Data.List module

classic Classic list List threaded Threaded
79 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Jon Fairbairn
Tikhon Jelvis <[hidden email]> writes:

> Idioms like (:[]) are not intuitive at all.

Can you explain that? Once one knows that all infix operators
can be used in sections (+1), (++"foo"), etc, that notation
should be obvious, both in reading and writing. It’s much better
to use ideas that are uniformly usable throughout the language
and can be learned once than to have to learn numerous specific
words.

I’m -1 on the proposal, obviously.

--
Jón Fairbairn                                 [hidden email]

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Tikhon Jelvis
The reason it's particularly unintuitive for lists is that we almost never explicitly construct lists using : and []. Sections like (+ 1) or (++ "Foo") reflect expressions like x + 1 and str ++ "Foo", but you simply never see x : [] in the wild. (In fact, in code review, I would always expect that to be rewritten as [x].)

In turn, this means that (:[]) doesn't convey my intentions as directly as possible. I want to build a list that contains a single element x, which I usually think of as [x]; the fact that I do this by consing x with an empty list is an implementation detail.

More generally, lists merit a special case because list notation is *already* a special case, and we can't do anything about that at this point!


On Tue, Aug 13, 2019, 10:49 Jon Fairbairn <[hidden email]> wrote:
Tikhon Jelvis <[hidden email]> writes:

> Idioms like (:[]) are not intuitive at all.

Can you explain that? Once one knows that all infix operators
can be used in sections (+1), (++"foo"), etc, that notation
should be obvious, both in reading and writing. It’s much better
to use ideas that are uniformly usable throughout the language
and can be learned once than to have to learn numerous specific
words.

I’m -1 on the proposal, obviously.

--
Jón Fairbairn                                 [hidden email]

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

David Feuer
In reply to this post by Taylor Fausak
I'm moderately +1 for consistency, and for NonEmpty as well. There is a concept here: create a container containing exactly one value. As Tikhon indicates, this is a different concept from pure. For example, a singleton ZipList has one element, while a pure one has infinitely many elements.

On Mon, Aug 12, 2019, 11:14 PM Taylor Fausak <[hidden email]> wrote:
I originally made this suggestion on GitLab, but I was told to make it here instead.

https://gitlab.haskell.org/ghc/ghc/issues/17042

---

# Add list singleton function

## Motivation

Sometimes it is convenient to have a function to wrap an element in a list. There are many ways to do this already, but none of them are as clear as a separate monomorphic function.

- `pure`: Polymorphic, works for any `Functor`.
- `pure @[]`: Noisy, requires `-XTypeApplications`.
- `(: [])`: Subjectively ugly.
- `(\x -> [x])`: Syntactically noisy.

This Twitter thread includes some additional commentary: https://twitter.com/taylorfausak/status/1159264862247280640

## Proposal

I would like to add a `singleton` function to `Data.List` that mirrors the `singleton` function for other containers: https://www.stackage.org/lts-14.0/hoogle?q=singleton

``` hs
singleton :: a -> [a]
singleton x = [x]
```

Other Haskell-like languages include this function:

- PureScript: https://pursuit.purescript.org/packages/purescript-lists/5.4.0/docs/Data.List#v:singleton
- Elm: https://package.elm-lang.org/packages/elm/core/latest/List#singleton
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Andrew Martin
I'm +1 on this. I've defined this function in my own code before. Using pure instead leads to harder-to-read code for future me and for collaborators. It also leads to worse type errors in the event that I mess something up.

On Tue, Aug 13, 2019 at 5:11 AM David Feuer <[hidden email]> wrote:
I'm moderately +1 for consistency, and for NonEmpty as well. There is a concept here: create a container containing exactly one value. As Tikhon indicates, this is a different concept from pure. For example, a singleton ZipList has one element, while a pure one has infinitely many elements.

On Mon, Aug 12, 2019, 11:14 PM Taylor Fausak <[hidden email]> wrote:
I originally made this suggestion on GitLab, but I was told to make it here instead.

https://gitlab.haskell.org/ghc/ghc/issues/17042

---

# Add list singleton function

## Motivation

Sometimes it is convenient to have a function to wrap an element in a list. There are many ways to do this already, but none of them are as clear as a separate monomorphic function.

- `pure`: Polymorphic, works for any `Functor`.
- `pure @[]`: Noisy, requires `-XTypeApplications`.
- `(: [])`: Subjectively ugly.
- `(\x -> [x])`: Syntactically noisy.

This Twitter thread includes some additional commentary: https://twitter.com/taylorfausak/status/1159264862247280640

## Proposal

I would like to add a `singleton` function to `Data.List` that mirrors the `singleton` function for other containers: https://www.stackage.org/lts-14.0/hoogle?q=singleton

``` hs
singleton :: a -> [a]
singleton x = [x]
```

Other Haskell-like languages include this function:

- PureScript: https://pursuit.purescript.org/packages/purescript-lists/5.4.0/docs/Data.List#v:singleton
- Elm: https://package.elm-lang.org/packages/elm/core/latest/List#singleton
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


--
-Andrew Thaddeus Martin

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Herbert Valerio Riedel-3
In reply to this post by David Feuer
>  There is a concept here: create a container containing exactly one value. As Tikhon indicates, this is a different concept from pure.

Fwiw, if you actually want a possibly meaningful/lawful reification of
the very specific "create any container containing exactly one item"
concept then an obvious approach would be to base it on the existing
(IMO under-appreciated) 'IsList' abstraction; in other words basically
something like

    singleton :: IsList l => Item l -> l
    singleton = fromListN 1 . (:[])

which could either be a method of `IsList` (with the default impl
above and an obvious lawful relationship to `fromList`/`toList`) or
just be a top-level binding exported from "GHC.List" and/or "GHC.Exts"
(which aren't governed by the Haskell Library Report and thus have a
lower barrier to entry).
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Matt
The point is to create a monomorphic variant that avoids the problems with the polymorphic `pure` and would be consistent with the other container-types. A polymorphic `singleton` would be useful, but - in the same way that `Map.fromLIst` and `Set.fromList` are (usefully!) monomorphic despite equivalent `IsList` methods, we'd still want to have a concrete `List.singleton :: a -> [a]`.

I see a lot of "Why isn't `pure` good enough here?", so I'd like to reiterate that `pure` has issues:

- It's not immediately+syntactically obvious what's being created. List.singleton is unambiguous to read.
- Polymorphism can cause unintended changes to behavior if GHC infers a different type than you expect. Consider `length (1,2)` confusion, `fmap (+1) (Left 1)` - while these have an obviously correct instance, it can still be confusing and yield potentially incorrect results.
- Monomorphic functions can often be very useful to inform GHC about a specific type you want to fix and allow the rest of inference to work around. Typed-holes provide much better information when you have concrete types rather than constrained polymorphic types.
- Finally, monomorphic functions can be used to prevent ambiguous type errors in the presence of OverloadedLists and OverloadedStrings, especially when every other method in the chain is written on Foldable or similar constraints.

Matt Parsons


On Tue, Aug 13, 2019 at 4:13 PM Herbert Valerio Riedel <[hidden email]> wrote:
>  There is a concept here: create a container containing exactly one value. As Tikhon indicates, this is a different concept from pure.

Fwiw, if you actually want a possibly meaningful/lawful reification of
the very specific "create any container containing exactly one item"
concept then an obvious approach would be to base it on the existing
(IMO under-appreciated) 'IsList' abstraction; in other words basically
something like

    singleton :: IsList l => Item l -> l
    singleton = fromListN 1 . (:[])

which could either be a method of `IsList` (with the default impl
above and an obvious lawful relationship to `fromList`/`toList`) or
just be a top-level binding exported from "GHC.List" and/or "GHC.Exts"
(which aren't governed by the Haskell Library Report and thus have a
lower barrier to entry).
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Herbert Valerio Riedel-3
> The point is to create a monomorphic variant [...]

But we already have at least two monomorphic variants to express this
with Haskell's concise native syntax and vocabulary which has by
design a preferential treatment of lists (it was considered even more
important than type-sigs so that we got the `:` cons operator for
lists and the `::` for type-sig annotations) -- so let's not try to
fight Haskell's core idioms by hiding them behind some trivial
additional redundant synonyms! I still fail to see the actual
*technical* problem being solved by the original proposal asking to
add yet another, wordy way to construct single-item-lists.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Matt
`(\x -> [x])` has the same polymorphism problem in the context of `OverloadedLists` as `pure`.

`(:[])` is also unsatisfactory. To parse it properly, you need to:

- Know that `:` is only allowed as an operator to prefix data constructors,
- Know that `[]` are not legal operator characters,
- Infer that you're intended to insert a space between the `:` and `[]` to get `(: [])`
- Recognize it as an operator section being used prefix as a normal function

I'm neither an expert nor a lifelong Haskeller, but I have been writing it in some professional capacity for four years now, and the operator section trips me up. I can't imagine less experienced folks find it easy or intuitive. You can't even search for it on hoogle: https://hoogle.haskell.org/?hoogle=(%3A%5B%5D)

Is `(:[])` a core idiom? I never see it in work code and I've never seen it in Hackage. To check, I grepped my software directory which has all my Haskell code, and got 122 matches of (:[]) over 1,768,231 loc (as given by wc -l **/*.hs).

Matt Parsons


On Tue, Aug 13, 2019 at 4:56 PM Herbert Valerio Riedel <[hidden email]> wrote:
> The point is to create a monomorphic variant [...]

But we already have at least two monomorphic variants to express this
with Haskell's concise native syntax and vocabulary which has by
design a preferential treatment of lists (it was considered even more
important than type-sigs so that we got the `:` cons operator for
lists and the `::` for type-sig annotations) -- so let's not try to
fight Haskell's core idioms by hiding them behind some trivial
additional redundant synonyms! I still fail to see the actual
*technical* problem being solved by the original proposal asking to
add yet another, wordy way to construct single-item-lists.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Taylor Fausak
I want to echo everything Matt Parsons is saying. I also want to publicly thank him for participating in this discussion and for making solid arguments. Thanks, Matt!

By way of explanation, I was motivated to propose this addition because a member of my team wondered aloud if there was a function to do this. I told them that I didn’t know of one, but I typically used `pure` in point-free expressions and `[x]` when the value had already been named. We searched around and couldn’t find anything:


We got to talking about other ways to express the same thing. (Everything we came up with has been seen in this thread already.) That got me wondering why there *wasn’t* a specific, monomorphic function for this. The omission seemed especially strange to my team member because they were familiar with Elm, which has this function. 

All that to say: This proposal is motivated by real confusion coming from a junior developer using Haskell at work. Consider how easy it is to discover and do something, rather than if it’s technically possible. 

On Aug 13, 2019, at 7:20 PM, Matt <[hidden email]> wrote:

`(\x -> [x])` has the same polymorphism problem in the context of `OverloadedLists` as `pure`.

`(:[])` is also unsatisfactory. To parse it properly, you need to:

- Know that `:` is only allowed as an operator to prefix data constructors,
- Know that `[]` are not legal operator characters,
- Infer that you're intended to insert a space between the `:` and `[]` to get `(: [])`
- Recognize it as an operator section being used prefix as a normal function

I'm neither an expert nor a lifelong Haskeller, but I have been writing it in some professional capacity for four years now, and the operator section trips me up. I can't imagine less experienced folks find it easy or intuitive. You can't even search for it on hoogle: https://hoogle.haskell.org/?hoogle=(%3A%5B%5D)

Is `(:[])` a core idiom? I never see it in work code and I've never seen it in Hackage. To check, I grepped my software directory which has all my Haskell code, and got 122 matches of (:[]) over 1,768,231 loc (as given by wc -l **/*.hs).

Matt Parsons


On Tue, Aug 13, 2019 at 4:56 PM Herbert Valerio Riedel <[hidden email]> wrote:
> The point is to create a monomorphic variant [...]

But we already have at least two monomorphic variants to express this
with Haskell's concise native syntax and vocabulary which has by
design a preferential treatment of lists (it was considered even more
important than type-sigs so that we got the `:` cons operator for
lists and the `::` for type-sig annotations) -- so let's not try to
fight Haskell's core idioms by hiding them behind some trivial
additional redundant synonyms! I still fail to see the actual
*technical* problem being solved by the original proposal asking to
add yet another, wordy way to construct single-item-lists.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Herbert Valerio Riedel-3
In reply to this post by Matt
> `(:[])` is also unsatisfactory

Which is a purely subjective assessment (and one I clearly disagree with)

> To parse it properly, you need to:
>
> - Know that `:` is only allowed as an operator to prefix data constructors,
> - Know that `[]` are not legal operator characters,
> - Infer that you're intended to insert a space between the `:` and `[]` to get `(: [])`
> - Recognize it as an operator section being used prefix as a normal function

Indeed, in order to parse a legit Haskell term, be it (0(,)), (:[0])
or (:".exe") or (:[]) you need to know the core Haskell98 syntax. I'm
aware that other languages such as Elm or Purescript favor different
ideals and design principles but that's not really a good argument to
make either; each language has its own idioms and point in the design
space.

I'm still waiting for a statement of the technical problem we're
trying to solve here which requires the introduction of a redundant
synonym for a concise facility we already have at our disposal by
virtue of the core Haskell98 syntax. Otherwise I'm afraid we're going
to be stuck in this discussion as everything on the topic has been
said and repeated in one way or another and so far we haven't reached
any consensus.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Matt
There have been 19 votes cast so far. We have twelve +1 votes. Of the -1 votes, three are because "`pure` is fine" and four are because "`(:[])` is fine." I summarized the issue with `pure` in my previous email, and there hasn't been any response or comment on the issues raised.

To summarize/quote the issues with `(:[])`:

> You can't even search for it on hoogle: https://hoogle.haskell.org/?hoogle=(%3A%5B%5D)
> Another advantage to having an explicit singleton function is discoverablity.

The discoverability of `(:[])` is bad.

> Is `(:[])` a core idiom? I never see it in work code and I've never seen it in Hackage. To check, I grepped my software directory which has all my Haskell code, and got 122 matches of (:[]) over 1,768,231 loc (as given by wc -l **/*.hs).

`(:[])` is not a common idiom (in the code sample I have; your mileage may vary).

> All alternatives to construct a list "anonymously" are confusing and take time to parse.
> The `(:[])` operator takes me a decent amount longer to parse and recognize, and I have seen intermediate-level Haskellers trip up over unspaced operators like this in several contexts.

The operator section is confusing and difficult to parse in this context.

Those are the three main problems that people have with `(:[])`, as far as I can tell.

Matt Parsons


On Wed, Aug 14, 2019 at 11:10 AM Herbert Valerio Riedel <[hidden email]> wrote:
> `(:[])` is also unsatisfactory

Which is a purely subjective assessment (and one I clearly disagree with)

> To parse it properly, you need to:
>
> - Know that `:` is only allowed as an operator to prefix data constructors,
> - Know that `[]` are not legal operator characters,
> - Infer that you're intended to insert a space between the `:` and `[]` to get `(: [])`
> - Recognize it as an operator section being used prefix as a normal function

Indeed, in order to parse a legit Haskell term, be it (0(,)), (:[0])
or (:".exe") or (:[]) you need to know the core Haskell98 syntax. I'm
aware that other languages such as Elm or Purescript favor different
ideals and design principles but that's not really a good argument to
make either; each language has its own idioms and point in the design
space.

I'm still waiting for a statement of the technical problem we're
trying to solve here which requires the introduction of a redundant
synonym for a concise facility we already have at our disposal by
virtue of the core Haskell98 syntax. Otherwise I'm afraid we're going
to be stuck in this discussion as everything on the topic has been
said and repeated in one way or another and so far we haven't reached
any consensus.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Oliver Charles-3
I'd also be interested in a kind of "reverse" argument - *if* we had this added, what are the costs? There are arguments of "no, pure/robot ninja is enough" - fine, we're not taking those away so you aren't required to use singleton  But what is the *downside* of having singleton?

It's basically write once, so I don't see an increase of maintenance burden in the prelude.

Of course, if people start to use it and you don't, there is a bit of conflict when it comes to reading others code. It's a slightly longer name, but the name itself is pretty clear. Even if you don't have it fully qualified, it's clear that it constructs a single element of something - the only syntax with potentially more information is the robot ninja operator (in the absence of overloaded lists), which makes it unambiguously about lists. So I think for people comfortable with pure/robot ninja, they would also be able to understand code using singleton. OTOH, the opposite doesn't seem to follow.

So, to the -1s, did I miss anything else?

On Wed, 14 Aug 2019, 6:37 pm Matt, <[hidden email]> wrote:
There have been 19 votes cast so far. We have twelve +1 votes. Of the -1 votes, three are because "`pure` is fine" and four are because "`(:[])` is fine." I summarized the issue with `pure` in my previous email, and there hasn't been any response or comment on the issues raised.

To summarize/quote the issues with `(:[])`:

> You can't even search for it on hoogle: https://hoogle.haskell.org/?hoogle=(%3A%5B%5D)
> Another advantage to having an explicit singleton function is discoverablity.

The discoverability of `(:[])` is bad.

> Is `(:[])` a core idiom? I never see it in work code and I've never seen it in Hackage. To check, I grepped my software directory which has all my Haskell code, and got 122 matches of (:[]) over 1,768,231 loc (as given by wc -l **/*.hs).

`(:[])` is not a common idiom (in the code sample I have; your mileage may vary).

> All alternatives to construct a list "anonymously" are confusing and take time to parse.
> The `(:[])` operator takes me a decent amount longer to parse and recognize, and I have seen intermediate-level Haskellers trip up over unspaced operators like this in several contexts.

The operator section is confusing and difficult to parse in this context.

Those are the three main problems that people have with `(:[])`, as far as I can tell.

Matt Parsons


On Wed, Aug 14, 2019 at 11:10 AM Herbert Valerio Riedel <[hidden email]> wrote:
> `(:[])` is also unsatisfactory

Which is a purely subjective assessment (and one I clearly disagree with)

> To parse it properly, you need to:
>
> - Know that `:` is only allowed as an operator to prefix data constructors,
> - Know that `[]` are not legal operator characters,
> - Infer that you're intended to insert a space between the `:` and `[]` to get `(: [])`
> - Recognize it as an operator section being used prefix as a normal function

Indeed, in order to parse a legit Haskell term, be it (0(,)), (:[0])
or (:".exe") or (:[]) you need to know the core Haskell98 syntax. I'm
aware that other languages such as Elm or Purescript favor different
ideals and design principles but that's not really a good argument to
make either; each language has its own idioms and point in the design
space.

I'm still waiting for a statement of the technical problem we're
trying to solve here which requires the introduction of a redundant
synonym for a concise facility we already have at our disposal by
virtue of the core Haskell98 syntax. Otherwise I'm afraid we're going
to be stuck in this discussion as everything on the topic has been
said and repeated in one way or another and so far we haven't reached
any consensus.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Sven Panne-2
In reply to this post by Matt
Am Mi., 14. Aug. 2019 um 19:37 Uhr schrieb Matt <[hidden email]>:
There have been 19 votes cast so far. We have twelve +1 votes.

-1 from me, so we have 7 -1s now. >:-) BTW: Simply counting a tiny amount of votes in a niche mailing list is not the best way to design APIs IMHO.
 
Of the -1 votes, three are because "`pure` is fine" and four are because "`(:[])` is fine." I summarized the issue with `pure` in my previous email, and there hasn't been any response or comment on the issues raised.

I still fail to see the issues with "pure". Let's be honest: If somebody has problems with polymorphic functions or operator sections, he will have a hard time with Haskell in general. These are fundamental things in your toolbox, and instead of coming up with tons of names which nobody can remember (Fairbairn threshold, anyone?) for trivial things, time is better spent educating people. Compared to the stuff you currently see in most modern libraries (GADTs, lenses, type-level computations, ...) understanding "pure" or "(: [])" will be your least problem.
 
To summarize/quote the issues with `(:[])`:

> You can't even search for it on hoogle: https://hoogle.haskell.org/?hoogle=(%3A%5B%5D)
> Another advantage to having an explicit singleton function is discoverablity.

The discoverability of `(:[])` is bad.

Why should I need to discover it when I can write it with 6 keystrokes (or even 4)? Or as "\x -> [x]", which is basically a matter of taste?
 
> Is `(:[])` a core idiom? I never see it in work code and I've never seen it in Hackage. To check, I grepped my software directory which has all my Haskell code, and got 122 matches of (:[]) over 1,768,231 loc (as given by wc -l **/*.hs).

`(:[])` is not a common idiom (in the code sample I have; your mileage may vary).

It is quite obvious to me why you don't find it much in code. You have lots of other ways to express the same thing:

   * You'll probably just use "[x]" if the argument already has a name.

   * If the argument doesn't have a name, you can give it one via "\x -> [x]" (which I consider "explicit", not "noisy") or perhaps via eta abstraction.

   * The code is intended to be polymorphic => "pure" is used.

   * Even if it's intended to be used monomorphic, there are often type signatures around to make "pure" monomorphic enough.

This doesn't leave many sensible places. Perhaps as an argument for a function, with very few type signatures around? Not a very convincing use case IMHO.

In a nutshell: Just like Herbert, I can't see the problem we're trying to solve. I would go even further: I would like to see a much more general Prelude/base library, not a more monomorphic one. Pages like https://haskell.fpcomplete.com/tutorial/synonyms cause quite a few "WTF?" moments caused by the (nowadays) useless synonyms...

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Sven Panne-2
In reply to this post by Oliver Charles-3
Am Mi., 14. Aug. 2019 um 21:35 Uhr schrieb Oliver Charles <[hidden email]>:
I'd also be interested in a kind of "reverse" argument - *if* we had this added, what are the costs? There are arguments of "no, pure/robot ninja is enough" - fine, we're not taking those away so you aren't required to use singleton  But what is the *downside* of having singleton? [...]

A similar argument comes up with basically every extension, and it is a very weak one. Code is mainly *read*, not written, so the less you need to know to read and understand code, the better it is. Lots of different ways to do the same thing makes programs harder to understand, and you ultimately end up with Perl. :-}  And if we take this argument seriously, we should probably add "doubleton" (synonym for "replicate 2"), "tripleton" (synonym for "replicate 3"), etc., too.  Hey, you don't have to use it after all, we're not taking away "replicate"...

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Francesco Ariis
In reply to this post by Sven Panne-2
On Wed, Aug 14, 2019 at 08:34:43PM +0100, Oliver Charles wrote:
> I'd also be interested in a kind of "reverse" argument - *if* we had this
> added, what are the costs? There are arguments of "no, pure/robot ninja is
> enough" - fine, we're not taking those away so you aren't required to use
> singleton  But what is the *downside* of having singleton?

I slightly prefer `singleton` myself; adding it to `Data.List`
*will* break some code though (Ambiguous occurrence ‘singleton’
etc etc. when you import, say, Data.Map unqualified).

On Wed, Aug 14, 2019 at 09:36:37PM +0200, Sven Panne wrote:
> Am Mi., 14. Aug. 2019 um 19:37 Uhr schrieb Matt <[hidden email]>:
>
> > There have been 19 votes cast so far. We have twelve +1 votes.
> >
>
> -1 from me, so we have 7 -1s now. >:-) BTW: Simply counting a tiny amount
> of votes in a niche mailing list is not the best way to design APIs IMHO.

Amen, let CLC reach consensus!

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Andreas Abel
In reply to this post by Sven Panne-2
Sven Panne wrote:

 > Code is mainly *read*, not written, so the less you need
 > to know to read and understand code, the better it is.

Yes, and this is an argument *for* singleton, not against:

1. singleton is already known to the Haskell reader from the other
collection types.

2. singleton is unambiguously invoking the image of creating a singleton
collection.

In contrast, "pure" invokes the image of creating a effect-free monadic
computation.  (:[]) invokes the image of a (mechanical) gorilla smiling
at you. ;-)  All these associations distract from reading the code.  In
both cases, a mental translation step is needed:

a) In the case of "pure", the conscious intervention that here we are
not concerned with non-determinism (the list monad), but just creating a
singleton collection.

b) In the case of "(:[])", the conscious intervention consists of
    - recognizing the decomposition (: [])
    - recognizing the operator section
    - understanding it as "cons something to the empty list"
    - understanding this as creating a singleton collection.

Both interventions hamper the flow of reading.

Of course, the procedure b) becomes automatic with use.  However, it is
still a significant barrier to the newcomer.

Cheers,
Andreas

P.S.: if the gorilla (:[]) is vanishing from the Agda code base, I am
mostly to be blamed for this.

On 2019-08-14 21:51, Sven Panne wrote:

> Am Mi., 14. Aug. 2019 um 21:35 Uhr schrieb Oliver Charles
> <[hidden email] <mailto:[hidden email]>>:
>
>     I'd also be interested in a kind of "reverse" argument - *if* we had
>     this added, what are the costs? There are arguments of "no,
>     pure/robot ninja is enough" - fine, we're not taking those away so
>     you aren't required to use singleton  But what is the *downside* of
>     having singleton? [...]
>
>
> A similar argument comes up with basically every extension, and it is a
> very weak one. Code is mainly *read*, not written, so the less you need
> to know to read and understand code, the better it is. Lots of different
> ways to do the same thing makes programs harder to understand, and you
> ultimately end up with Perl. :-}  And if we take this argument
> seriously, we should probably add "doubleton" (synonym for "replicate
> 2"), "tripleton" (synonym for "replicate 3"), etc., too.  Hey, you don't
> have to use it after all, we're not taking away "replicate"...
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Scott Marks
I confess I am a minimalist. Been coding Haskell for a year after a break (my 1982 dissertation was “Optimization of Functional Programs” so my interest goes back a ways).  Were I the God of Haskell I would go down the above-mentioned synonym list and deprecate all the less-general “return” things. 

I confess also that the semantics of “pure” seems in some cases ((,), etc) to have been chosen for pragmatic reason; inevitably one must choose an embedding when there is a choice, and “I got there first” can be justified if it produces lots of elegant simplicity. To my taste it’s too bad that Collection means “ordered collection” but I imagine that there are more applications in which deterministic iteration is useful. 

All that being said, I vote for singleton as a readable method name for Collection instances. 
To my way of thinking this implies picking a Collection class and moving it closer to the Root of all Haskell. 

On Thu, Aug 15, 2019 at 13:23 Andreas Abel <[hidden email]> wrote:
Sven Panne wrote:

 > Code is mainly *read*, not written, so the less you need
 > to know to read and understand code, the better it is.

Yes, and this is an argument *for* singleton, not against:

1. singleton is already known to the Haskell reader from the other
collection types.

2. singleton is unambiguously invoking the image of creating a singleton
collection.

In contrast, "pure" invokes the image of creating a effect-free monadic
computation.  (:[]) invokes the image of a (mechanical) gorilla smiling
at you. ;-)  All these associations distract from reading the code.  In
both cases, a mental translation step is needed:

a) In the case of "pure", the conscious intervention that here we are
not concerned with non-determinism (the list monad), but just creating a
singleton collection.

b) In the case of "(:[])", the conscious intervention consists of
    - recognizing the decomposition (: [])
    - recognizing the operator section
    - understanding it as "cons something to the empty list"
    - understanding this as creating a singleton collection.

Both interventions hamper the flow of reading.

Of course, the procedure b) becomes automatic with use.  However, it is
still a significant barrier to the newcomer.

Cheers,
Andreas

P.S.: if the gorilla (:[]) is vanishing from the Agda code base, I am
mostly to be blamed for this.

On 2019-08-14 21:51, Sven Panne wrote:
> Am Mi., 14. Aug. 2019 um 21:35 Uhr schrieb Oliver Charles
> <[hidden email] <mailto:[hidden email]>>:
>
>     I'd also be interested in a kind of "reverse" argument - *if* we had
>     this added, what are the costs? There are arguments of "no,
>     pure/robot ninja is enough" - fine, we're not taking those away so
>     you aren't required to use singleton  But what is the *downside* of
>     having singleton? [...]
>
>
> A similar argument comes up with basically every extension, and it is a
> very weak one. Code is mainly *read*, not written, so the less you need
> to know to read and understand code, the better it is. Lots of different
> ways to do the same thing makes programs harder to understand, and you
> ultimately end up with Perl. :-}  And if we take this argument
> seriously, we should probably add "doubleton" (synonym for "replicate
> 2"), "tripleton" (synonym for "replicate 3"), etc., too.  Hey, you don't
> have to use it after all, we're not taking away "replicate"...
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Carter Schonwald
In reply to this post by Andrew Lelechenko
Hard -1, , i'm not seeing a useful high impact payoff 

plus its more verbose and adhoc than pure and more confusing than (:[])

I actually initially thought this thread was about Type Singletons and or Proxy style apis using List as the term level form, it actually took me a few minutes of reading everyone's replies to disambiguate

i'm open to changing my mind later if i can convince myself, but -1 for now 

On Mon, Aug 12, 2019 at 3:53 PM Andrew Lelechenko <[hidden email]> wrote:
- `pure`: Polymorphic, works for any `Functor`.

It is OK to have polymorphic folds and length, so what is wrong with pure? 

Adding singleton to Data.List is a breaking change, when Data.Map.singleton was exported unqualified. 
And there is no singleton in Data.List.NonEmpty as well. 

-1 from me.

Best regards,
Andrew

On 12 Aug 2019, at 19:36, Brent Yorgey <[hidden email]> wrote:

At the risk of completely derailing the conversation, I have always called this the "robot monkey operator".  I fail to see what is so ninja-like about it.

Anyway, I think I am +1 on adding Data.List.singleton.

-Brent

On Mon, Aug 12, 2019, 12:35 PM Zemyla <[hidden email]> wrote:
I also like the ninja-robot operator, because it's visually
interesting and easy to search for.

Also, if you're importing several libraries which already use
"singleton", then you have to use "List.singleton" every time, which
is far uglier to me.

On Mon, Aug 12, 2019 at 12:03 PM Herbert Valerio Riedel
<[hidden email]> wrote:
>
> > - `(:[])`: Subjectively ugly.
>
> I consider "subjectively ugly" to be a non-technical and thus really
> weak argument to dismiss the list-idiomatic ninja-robot-operator (:[])
> which also happens to be shorter than the proposed alias for it. I for
> one don't see a significant benefit for adding a redundant synonym to
> `Data.List` and are thus -1 on this.
>
> > singleton :: a -> [a]
> > singleton x = [x]
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Bryan Richter-2
On 8/16/19 4:17 AM, Carter Schonwald wrote:

> Hard -1, , i'm not seeing a useful high impact payoff
>
> plus its more verbose and adhoc than pure and more confusing than
> (:[])
>
> I actually initially thought this thread was about Type Singletons
> and or Proxy style apis using List as the term level form, it
> actually took me a few minutes of reading everyone's replies to
> disambiguate

If a value-level 'singleton' is confusing to anybody, I have really[1]
quite[2] terrible[3], in[4] fact[5] downright[6] awful[7] news[8]. :)

+1 to Data.List.singleton and Data.List.NonEmpty.singleton from me in
the peanut gallery. I agree with the sentiment that 'pure @ []' means
"side effect-free nondeterministic value", which is quite different
than meaning "a list with one element", and is therefore possibly more
ad hoc than using the well-established 'singleton'.

But I also joyfully assent to the decision of the CLC! Besides the
possibility for breakage (can we use head.hackage to get hard data
here?), I have not seen a single "technical", data-based argument from
either side. Even asking the proponents to provide technical
arguments, after all, is a subjective criterion.

With respectful acknowledgement of all positions taken,

-Bryan

[1]: https://hackage.haskell.org/package/bytestring/docs/Data-ByteString.html#v:singleton
[2]: https://hackage.haskell.org/package/containers/docs/Data-IntMap-Internal.html#v:singleton
[3]: https://hackage.haskell.org/package/text/docs/Data-Text.html#v:singleton
[4]: https://hackage.haskell.org/package/vector/docs/Data-Vector.html#v:singleton
[5]: https://hackage.haskell.org/package/unordered-containers/docs/Data-HashSet.html#v:singleton
[6]: https://hackage.haskell.org/package/lens/docs/Control-Lens-Internal-Deque.html#v:singleton
[7]: https://hackage.haskell.org/package/Cabal/docs/Distribution-Compat-DList.html#v:singleton
[8]: https://hackage.haskell.org/package/memory/docs/Data-ByteArray.html#v:singleton

p.s. I've intentionally chosen eight different packages, some of which
include a number of different 'singleton's!

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add singleton function to Data.List module

Ignat Insarov
In reply to this post by Herbert Valerio Riedel-3
I'd like to derail this conversation into remembering the "C, Unix hoax" joke.
https://www.gnu.org/fun/jokes/unix-hoax.html

> We stopped when we got a clean compile on the following syntax:
>
>     for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);

We humans find it easier to think in words, which are singleton blobs
of sense requiring no parsing, no compilation, but immediately
obvious. The "monkey face" here is not one, not two, but four distinct
blobs. This is in fact a technical argument against it, though
referring to the technic of human cognition rather than machine's.

In this perspective, is it not clear that we should strive away from
symbol soup idioms? Let us write programs for people to read.

On Mon, 12 Aug 2019 at 20:03, Herbert Valerio Riedel <[hidden email]> wrote:

>
> > - `(:[])`: Subjectively ugly.
>
> I consider "subjectively ugly" to be a non-technical and thus really
> weak argument to dismiss the list-idiomatic ninja-robot-operator (:[])
> which also happens to be shorter than the proposed alias for it. I for
> one don't see a significant benefit for adding a redundant synonym to
> `Data.List` and are thus -1 on this.
>
> > singleton :: a -> [a]
> > singleton x = [x]
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
1234