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

Kris Nuttycombe
Since this has remained contentious, I'd like to contribute my +1 to the argument, and to express my support for the points that Nathan and Matt have raised. To this point in the discussion, however, I have not seen raised the perspective that I hold, and so I'm going to add another color to the bikeshed.

My point of view here is informed by my efforts to teach my children to program, using Haskell. 

In every case where we define a typeclass instance, we write the implementation of that instance as a number of monomorphic functions. My position is that these monomorphic functions should always be exported directly, perhaps from an `.Internal` module. 

My preferred way of writing typeclass instances is just this: I create two modules, `Foo.Bar` and `Foo.Bar.Internal`. `Foo.Bar` is used only to selectively reexport from `Foo.Bar.Internal`, which is where the relevant types and typeclass instances are defined. For each typeclass method to be implemented, I define a top-level monomorphic function, and this function is used in the implementation of the instance; in this case, it would look like:

module Data.List.Internal where
  ...

  singleton :: x -> [x]
  singleton x = [x]

instance Applicative [] where
  pure = singleton
  ...

When followed consistently, this gives the end user the greatest flexibility in choosing whether to use the monomorphic version (in a context where they want the compiler to alert them if the type changes) or the polymorphic one. I dearly wish, for example, that this approach were followed in `Data.Time.Clock`, for example, where a good deal of the important functionality is awkwardly hidden in `Num` and `Integral` instances (which, as an aside, are highly inappropriate).

In conclusion, I think that the proposal for Data.List.singleton is a good one - I just wish that it went a great deal further.

Kris

On Wed, Aug 21, 2019 at 6:32 AM Taylor Fausak <[hidden email]> wrote:
Thanks for saying that, Nathan! I agree wholeheartedly.

To George and the CLC: I'm disappointed to hear that I inadvertently suggested something that would require changing the Haskell Language Report. It is my understanding that work on the report has more or less stalled [1], and I would hate for this simple addition to be caught in that quagmire.

Your mention of the report encouraged me to look for differences between the current Data.List module and the one specified in the report [2]. Aside from the obvious Foldable/Traversable changes brought by the FTP proposal, it didn't take long to find a difference: the uncons function [3]. I found its source in GHC.List [4], which pointed me to a Trac issue [5], a mailing list thread [6], and a Phabricator differential [7].

I bring this up not because I expect the process to be exactly the same today as it was five years ago, but because the simple addition of the uncons function was accepted without nearly as much discussion. Also it was notably accepted without any mention of the report at all. Has something changed in the meantime, or did I suggest something that hit a nerve with the community?

Regardless, I'm happy to hear that the CLC is considering my proposal among themselves. Is there an expected timeline? (I'm looking for a rough order of magnitude, not an exact date.) Thanks!


On Wed, Aug 21, 2019, at 6:22 AM, Nathan Bouscal wrote:
Hi all,

I would strongly encourage anyone inclined to say things like “there's no benefit in having the function” to consider reframing the sentiment as “I wouldn’t benefit from having the function, and don’t understand the benefit others will gain.” Once you’ve done that reframe, you can notice that there’s a lack of understanding toward which the appropriate emotional stance is curiosity, not dismissiveness. A lot of people have clearly expressed in this thread that they would benefit from this function, and when you assert as fact that such benefit does not exist, you’re implicitly dismissing and devaluing their experience. 

Independent of any technical merits or readability concerns per se, there is a signaling aspect to this discussion. Already this thread has been referenced many times on social media, and it’s sending a very loud signal: “we don’t want you here”. Not because of the content of the discussion, but because of its tone. I happen to think that Haskell is a fantastic language for beginners, and I’ve been watching in real time as potential learners are deciding it isn’t for them. I’ve also been seeing experienced Haskellers deciding it’s not worth it to participate in the libraries process. You can argue as much as you want that people are wrong to get that signal from this thread, that they’re misinterpreting the comments here, etc, but none of that changes the outcome. We can do better than this.


On the proposal itself: I’ve been writing Haskell for several years now and have founded a company that uses Haskell in production, so I’d like to think I’m at least a step or two beyond “beginner”, and yet I cannot recall the last time I saw (:[]) in my code or anyone else’s, and seeing it here caused me to double-take and take a moment to mentally parse it. If that’s the case for me, I’m sure it must be far worse for an actual beginner. Building things by composing primitives is good, but if anyone put this operator into my codebase I’d likely flag it in code review. Readability isn’t about whether it’s possible to read something, it’s about how easy it is to read, and for me this operator doesn’t pass that test. Personally I tend to use pure, but a monomorphic option would be better. I would happily change to using singleton if it becomes available, and am a +1 on the proposal for both List and NonEmpty.


Nathan


On Wed, Aug 21, 2019 at 6:32 AM George Wilson <[hidden email]> wrote:
Hi Taylor,

I'm on the Core Libraries Committee. Thank you for your proposal.
Regarding the +-1 messages in this thread, they are useful to gauge
community opinion, but they are not votes because the libraries
process is not determined by a vote.

Despite seeming innocuous, the proposed change requires careful
consideration: Data.List is specified by the Haskell Report, so adding
this function would affect the report.
While simple changes to base are typically handled directly by one of
base's maintainers, this change is report-affecting, so it is
"controversial" (as defined in [1]). Hence the CLC is discussing the
proposed change amongst ourselves before a maintainer makes their
decision.


Cheers,
George





On Tue, 20 Aug 2019 at 11:24, Taylor Fausak <[hidden email]> wrote:
>
> It has been a week since I submitted my proposal. During that time, 28 people voted, with 16 expressing approval and 12 expressing disapproval. To everyone that voted so far: Thank you! You made for interesting discussion.
>
> I still feel that Haskell would be improved by the addition of a `singleton` function to the `Data.List` module. (And also `Data.List.NonEmpty`, even though that wasn't part of my original proposal.) I would be happy to open a merge request adding code, tests, and documentation.
>
> I haven't done so yet because I don't know what the next steps are. Can someone from the CLC tell me how an official approval or rejection can be reached, and how long that might take? Thanks!
>
> On Mon, Aug 19, 2019, at 6:39 AM, Helmut Schmidt wrote:
>
>
> Andreas, you seem to be mistaken there'd only be one container API? But there's several container APIs besides "Data.Set" which provide some collection of elements!
>
>
>
>
>
>
>
>
>
>
>
> Am Mo., 19. Aug. 2019 um 08:16 Uhr schrieb Andreas Abel <[hidden email]>:
>
> Helmut, do you actually know the container APIs?
>
> Show me cons and append in Data.Set!
>
> On 2019-08-18 19:40, Helmut Schmidt wrote:
> >
> >
> > Am So., 18. Aug. 2019 um 17:17 Uhr schrieb Oliver Charles
> >
> >     On Sun, 18 Aug 2019, 5:47 pm Helmut Schmidt,
> >     <[hidden email]
> >     <mailto:[hidden email]>> wrote:
> >
> >
> >         All these philosophical arguments calling for "consistency" with
> >         the container APIs or that function need words for the human
> >         mind to comprehend seem short-sighted to me. If we were
> >         consistent about the proposal itself we'd also demand to add
> >
> >            cons = (:)
> >
> >            empty = []
> >
> >            toList = id
> >
> >            fromList = id
> >
> >
> >     I honestly have no problem with any of these.
> >
> >
> > I forgot
> >
> >      append = (++)
> >
> > We also need to address another elephant in the room... those pesky
> > tuples and their special privileged non-wordy syntax!
> >
> >     pair = (,)
> >
> >     triple = (,,)
> >
> >     quadruple = (,,,)
> >
> >     quituple = (,,,,)
> >
> >     sextuple = (,,,,,)
> >
> >     septuble = (,,,,,,)
> >
> >     octuple = (,,,,,,,)
> >
> > If Haskell were invented in this century's EU Haskell source code would
> > be littered with €s instead of $s but then again I wonder why £ wasn't
> > picked. But I digress. We can kill two birds with one stone here:
> >
> >     apply = ($)
> >
> >     strictApply = ($!)
> >
> >     compose = (.)
> >
> >
> > It's fun to imagine how code using those definitions would like! But
> > it's still a -1 for me, sorry!
> >
> >
> >
> >
> > _______________________________________________
> > Libraries mailing list
> >
>
> _______________________________________________
> Libraries mailing list
>
>
> _______________________________________________
> Libraries mailing list
_______________________________________________
Libraries mailing list
_______________________________________________
Libraries mailing list


_______________________________________________
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
|

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

Sven Panne-2
In reply to this post by Nathan Bouscal
Am Mi., 21. Aug. 2019 um 12:22 Uhr schrieb Nathan Bouscal <[hidden email]>:
I would strongly encourage anyone inclined to say things like “there's no benefit in having the function” to consider reframing the sentiment as “I wouldn’t benefit from having the function, and don’t understand the benefit others will gain.” Once you’ve done that reframe, you can notice that there’s a lack of understanding toward which the appropriate emotional stance is curiosity, not dismissiveness. A lot of people have clearly expressed in this thread that they would benefit from this function, and when you assert as fact that such benefit does not exist, you’re implicitly dismissing and devaluing their experience. [...]

There is also another side of the coin: A lot of people have clearly expressed counterarguments,  so *their* experience has been equally "dismissed" or "devalued". Reframing the discussion shouldn't be biased, otherwise it's just a cheap trick to make one side of the discussion more valuable/stronger. Furthermore, a technical discussion doesn't need to be an excercise in nonviolent communication, as long as people don't start insulting each other.

I think the main problem of this discussion (and other similar threads on this list) is that there is no consensus about how to design an API. IMHO, piling up little helpers just because they came up in a few places is a recipe for horrible, bloated APIs. The questions one should ask are "Does it generalize things?", "Does it make my API more powerful?" (i.e. can I do things I couldn't do before), "Does it remove common pitfalls?" etc.  But this is just my personal view, obviously others seem to disagree.... :-/

_______________________________________________
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

Haskell - Libraries mailing list
In reply to this post by George Wilson
I have some data to contribute, from our proprietary codebase of some 4MLoC.  We are perhaps unusual in having the singleton function on lists already for 10 years, so it is easy to do a comparison of the frequency of use.

The robot monkey (:[]) has 378 uses.
Monkey with a space (: []) has 36 uses.
The list singleton function has 18 uses.

We also have many other singleton functions at more than 20 different types (vector, tuple, map, set, interval, relation, dict, expression, etc), totalling 1893 uses, so the concept/vocabulary is pretty well-known.

In addition, I counted the number of direct constructions of lists that use :[] unparenthesised, i.e like x:y:[], and there are 489.

I find it interesting that given the choice of “singleton” vs direct construction or a partially applied operator, our devs seem to prefer the brevity and naturality of the colon.

Regards,
    Malcolm

> On 21 Aug 2019, at 06:31, George Wilson <[hidden email]> wrote:
>
> Hi Taylor,
>
> I'm on the Core Libraries Committee. Thank you for your proposal.
> Regarding the +-1 messages in this thread, they are useful to gauge
> community opinion, but they are not votes because the libraries
> process is not determined by a vote.
>
> Despite seeming innocuous, the proposed change requires careful
> consideration: Data.List is specified by the Haskell Report, so adding
> this function would affect the report.
> While simple changes to base are typically handled directly by one of
> base's maintainers, this change is report-affecting, so it is
> "controversial" (as defined in [1]). Hence the CLC is discussing the
> proposed change amongst ourselves before a maintainer makes their
> decision.
>
> [1] https://wiki.haskell.org/Library_submissions
>
> Cheers,
> George
>
>
>
>
>
>> On Tue, 20 Aug 2019 at 11:24, Taylor Fausak <[hidden email]> wrote:
>>
>> It has been a week since I submitted my proposal. During that time, 28 people voted, with 16 expressing approval and 12 expressing disapproval. To everyone that voted so far: Thank you! You made for interesting discussion.
>>
>> I still feel that Haskell would be improved by the addition of a `singleton` function to the `Data.List` module. (And also `Data.List.NonEmpty`, even though that wasn't part of my original proposal.) I would be happy to open a merge request adding code, tests, and documentation.
>>
>> I haven't done so yet because I don't know what the next steps are. Can someone from the CLC tell me how an official approval or rejection can be reached, and how long that might take? Thanks!
>>
>> On Mon, Aug 19, 2019, at 6:39 AM, Helmut Schmidt wrote:
>>
>>
>> Andreas, you seem to be mistaken there'd only be one container API? But there's several container APIs besides "Data.Set" which provide some collection of elements!
>>
>> https://hackage.haskell.org/package/dlist-0.8.0.7/docs/Data-DList.html#v:cons
>>
>> https://hackage.haskell.org/package/dlist-0.8.0.7/docs/Data-DList.html#v:append
>>
>>
>>
>>
>> https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text.html#v:cons
>>
>> https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text.html#v:append
>>
>> http://hackage.haskell.org/package/vector-0.12.0.3/docs/Data-Vector.html#v:cons
>>
>> https://hackage.haskell.org/package/bytestring-0.10.10.0/docs/Data-ByteString.html#v:cons
>>
>> https://hackage.haskell.org/package/bytestring-0.10.10.0/docs/Data-ByteString.html#v:append
>>
>> Am Mo., 19. Aug. 2019 um 08:16 Uhr schrieb Andreas Abel <[hidden email]>:
>>
>> Helmut, do you actually know the container APIs?
>>
>> Show me cons and append in Data.Set!
>>
>>> On 2019-08-18 19:40, Helmut Schmidt wrote:
>>>
>>>
>>> Am So., 18. Aug. 2019 um 17:17 Uhr schrieb Oliver Charles
>>> <[hidden email] <mailto:[hidden email]>>:
>>>
>>>    On Sun, 18 Aug 2019, 5:47 pm Helmut Schmidt,
>>>    <[hidden email]
>>>    <mailto:[hidden email]>> wrote:
>>>
>>>
>>>        All these philosophical arguments calling for "consistency" with
>>>        the container APIs or that function need words for the human
>>>        mind to comprehend seem short-sighted to me. If we were
>>>        consistent about the proposal itself we'd also demand to add
>>>
>>>           cons = (:)
>>>
>>>           empty = []
>>>
>>>           toList = id
>>>
>>>           fromList = id
>>>
>>>
>>>    I honestly have no problem with any of these.
>>>
>>>
>>> I forgot
>>>
>>>     append = (++)
>>>
>>> We also need to address another elephant in the room... those pesky
>>> tuples and their special privileged non-wordy syntax!
>>>
>>>    pair = (,)
>>>
>>>    triple = (,,)
>>>
>>>    quadruple = (,,,)
>>>
>>>    quituple = (,,,,)
>>>
>>>    sextuple = (,,,,,)
>>>
>>>    septuble = (,,,,,,)
>>>
>>>    octuple = (,,,,,,,)
>>>
>>> If Haskell were invented in this century's EU Haskell source code would
>>> be littered with €s instead of $s but then again I wonder why £ wasn't
>>> picked. But I digress. We can kill two birds with one stone here:
>>>
>>>    apply = ($)
>>>
>>>    strictApply = ($!)
>>>
>>>    compose = (.)
>>>
>>>
>>> It's fun to imagine how code using those definitions would like! But
>>> it's still a -1 for me, sorry!
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> 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

Elliot Cameron-2
We also use the money face regularly in our code bases, but I think it's only because the singleton function for lists is not already defined. Every time I see/use it I wince a little.

Some devs I know will go to lengths to avoid an extra import line. So you often see 'maybe x id' instead of 'fromMaybe x' and 'flip traverse' instead of 'for'.

No other containers are in Prelude and must have their APIs imported qualified. So they don't suffer from this bias against imports.

In any code base the defines it's own idioms, like singleton on lists, you have to imagine that what's obviously on Hackage and what is proprietary will not get the same level of commitment.

P.S. Based on arguments against non-fundanental combinators, I suppose we should remove 'fromMaybe' and 'for' since they are not fundamental?

This debate is definitely more ideological than I think anyone quite realized at first. At the very least, having the CLC's position clearly documented might help in the future.

On Thu, Aug 22, 2019, 7:12 AM Malcolm Wallace via Libraries <[hidden email]> wrote:
I have some data to contribute, from our proprietary codebase of some 4MLoC.  We are perhaps unusual in having the singleton function on lists already for 10 years, so it is easy to do a comparison of the frequency of use.

The robot monkey (:[]) has 378 uses.
Monkey with a space (: []) has 36 uses.
The list singleton function has 18 uses.

We also have many other singleton functions at more than 20 different types (vector, tuple, map, set, interval, relation, dict, expression, etc), totalling 1893 uses, so the concept/vocabulary is pretty well-known.

In addition, I counted the number of direct constructions of lists that use :[] unparenthesised, i.e like x:y:[], and there are 489.

I find it interesting that given the choice of “singleton” vs direct construction or a partially applied operator, our devs seem to prefer the brevity and naturality of the colon.

Regards,
    Malcolm

> On 21 Aug 2019, at 06:31, George Wilson <[hidden email]> wrote:
>
> Hi Taylor,
>
> I'm on the Core Libraries Committee. Thank you for your proposal.
> Regarding the +-1 messages in this thread, they are useful to gauge
> community opinion, but they are not votes because the libraries
> process is not determined by a vote.
>
> Despite seeming innocuous, the proposed change requires careful
> consideration: Data.List is specified by the Haskell Report, so adding
> this function would affect the report.
> While simple changes to base are typically handled directly by one of
> base's maintainers, this change is report-affecting, so it is
> "controversial" (as defined in [1]). Hence the CLC is discussing the
> proposed change amongst ourselves before a maintainer makes their
> decision.
>
> [1] https://wiki.haskell.org/Library_submissions
>
> Cheers,
> George
>
>
>
>
>
>> On Tue, 20 Aug 2019 at 11:24, Taylor Fausak <[hidden email]> wrote:
>>
>> It has been a week since I submitted my proposal. During that time, 28 people voted, with 16 expressing approval and 12 expressing disapproval. To everyone that voted so far: Thank you! You made for interesting discussion.
>>
>> I still feel that Haskell would be improved by the addition of a `singleton` function to the `Data.List` module. (And also `Data.List.NonEmpty`, even though that wasn't part of my original proposal.) I would be happy to open a merge request adding code, tests, and documentation.
>>
>> I haven't done so yet because I don't know what the next steps are. Can someone from the CLC tell me how an official approval or rejection can be reached, and how long that might take? Thanks!
>>
>> On Mon, Aug 19, 2019, at 6:39 AM, Helmut Schmidt wrote:
>>
>>
>> Andreas, you seem to be mistaken there'd only be one container API? But there's several container APIs besides "Data.Set" which provide some collection of elements!
>>
>> https://hackage.haskell.org/package/dlist-0.8.0.7/docs/Data-DList.html#v:cons
>>
>> https://hackage.haskell.org/package/dlist-0.8.0.7/docs/Data-DList.html#v:append
>>
>>
>>
>>
>> https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text.html#v:cons
>>
>> https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text.html#v:append
>>
>> http://hackage.haskell.org/package/vector-0.12.0.3/docs/Data-Vector.html#v:cons
>>
>> https://hackage.haskell.org/package/bytestring-0.10.10.0/docs/Data-ByteString.html#v:cons
>>
>> https://hackage.haskell.org/package/bytestring-0.10.10.0/docs/Data-ByteString.html#v:append
>>
>> Am Mo., 19. Aug. 2019 um 08:16 Uhr schrieb Andreas Abel <[hidden email]>:
>>
>> Helmut, do you actually know the container APIs?
>>
>> Show me cons and append in Data.Set!
>>
>>> On 2019-08-18 19:40, Helmut Schmidt wrote:
>>>
>>>
>>> Am So., 18. Aug. 2019 um 17:17 Uhr schrieb Oliver Charles
>>> <[hidden email] <mailto:[hidden email]>>:
>>>
>>>    On Sun, 18 Aug 2019, 5:47 pm Helmut Schmidt,
>>>    <[hidden email]
>>>    <mailto:[hidden email]>> wrote:
>>>
>>>
>>>        All these philosophical arguments calling for "consistency" with
>>>        the container APIs or that function need words for the human
>>>        mind to comprehend seem short-sighted to me. If we were
>>>        consistent about the proposal itself we'd also demand to add
>>>
>>>           cons = (:)
>>>
>>>           empty = []
>>>
>>>           toList = id
>>>
>>>           fromList = id
>>>
>>>
>>>    I honestly have no problem with any of these.
>>>
>>>
>>> I forgot
>>>
>>>     append = (++)
>>>
>>> We also need to address another elephant in the room... those pesky
>>> tuples and their special privileged non-wordy syntax!
>>>
>>>    pair = (,)
>>>
>>>    triple = (,,)
>>>
>>>    quadruple = (,,,)
>>>
>>>    quituple = (,,,,)
>>>
>>>    sextuple = (,,,,,)
>>>
>>>    septuble = (,,,,,,)
>>>
>>>    octuple = (,,,,,,,)
>>>
>>> If Haskell were invented in this century's EU Haskell source code would
>>> be littered with €s instead of $s but then again I wonder why £ wasn't
>>> picked. But I digress. We can kill two birds with one stone here:
>>>
>>>    apply = ($)
>>>
>>>    strictApply = ($!)
>>>
>>>    compose = (.)
>>>
>>>
>>> It's fun to imagine how code using those definitions would like! But
>>> it's still a -1 for me, sorry!
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> 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

_______________________________________________
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

Elliot Cameron-2
Hilariously, I just saw this article on my feed which sheepishly admits that it's example of "singleton" isn't actually a thing in Data.List: https://typeclasses.com/featured/singleton

On Thu, Aug 22, 2019 at 8:11 AM Elliot Cameron <[hidden email]> wrote:
We also use the money face regularly in our code bases, but I think it's only because the singleton function for lists is not already defined. Every time I see/use it I wince a little.

Some devs I know will go to lengths to avoid an extra import line. So you often see 'maybe x id' instead of 'fromMaybe x' and 'flip traverse' instead of 'for'.

No other containers are in Prelude and must have their APIs imported qualified. So they don't suffer from this bias against imports.

In any code base the defines it's own idioms, like singleton on lists, you have to imagine that what's obviously on Hackage and what is proprietary will not get the same level of commitment.

P.S. Based on arguments against non-fundanental combinators, I suppose we should remove 'fromMaybe' and 'for' since they are not fundamental?

This debate is definitely more ideological than I think anyone quite realized at first. At the very least, having the CLC's position clearly documented might help in the future.

On Thu, Aug 22, 2019, 7:12 AM Malcolm Wallace via Libraries <[hidden email]> wrote:
I have some data to contribute, from our proprietary codebase of some 4MLoC.  We are perhaps unusual in having the singleton function on lists already for 10 years, so it is easy to do a comparison of the frequency of use.

The robot monkey (:[]) has 378 uses.
Monkey with a space (: []) has 36 uses.
The list singleton function has 18 uses.

We also have many other singleton functions at more than 20 different types (vector, tuple, map, set, interval, relation, dict, expression, etc), totalling 1893 uses, so the concept/vocabulary is pretty well-known.

In addition, I counted the number of direct constructions of lists that use :[] unparenthesised, i.e like x:y:[], and there are 489.

I find it interesting that given the choice of “singleton” vs direct construction or a partially applied operator, our devs seem to prefer the brevity and naturality of the colon.

Regards,
    Malcolm

> On 21 Aug 2019, at 06:31, George Wilson <[hidden email]> wrote:
>
> Hi Taylor,
>
> I'm on the Core Libraries Committee. Thank you for your proposal.
> Regarding the +-1 messages in this thread, they are useful to gauge
> community opinion, but they are not votes because the libraries
> process is not determined by a vote.
>
> Despite seeming innocuous, the proposed change requires careful
> consideration: Data.List is specified by the Haskell Report, so adding
> this function would affect the report.
> While simple changes to base are typically handled directly by one of
> base's maintainers, this change is report-affecting, so it is
> "controversial" (as defined in [1]). Hence the CLC is discussing the
> proposed change amongst ourselves before a maintainer makes their
> decision.
>
> [1] https://wiki.haskell.org/Library_submissions
>
> Cheers,
> George
>
>
>
>
>
>> On Tue, 20 Aug 2019 at 11:24, Taylor Fausak <[hidden email]> wrote:
>>
>> It has been a week since I submitted my proposal. During that time, 28 people voted, with 16 expressing approval and 12 expressing disapproval. To everyone that voted so far: Thank you! You made for interesting discussion.
>>
>> I still feel that Haskell would be improved by the addition of a `singleton` function to the `Data.List` module. (And also `Data.List.NonEmpty`, even though that wasn't part of my original proposal.) I would be happy to open a merge request adding code, tests, and documentation.
>>
>> I haven't done so yet because I don't know what the next steps are. Can someone from the CLC tell me how an official approval or rejection can be reached, and how long that might take? Thanks!
>>
>> On Mon, Aug 19, 2019, at 6:39 AM, Helmut Schmidt wrote:
>>
>>
>> Andreas, you seem to be mistaken there'd only be one container API? But there's several container APIs besides "Data.Set" which provide some collection of elements!
>>
>> https://hackage.haskell.org/package/dlist-0.8.0.7/docs/Data-DList.html#v:cons
>>
>> https://hackage.haskell.org/package/dlist-0.8.0.7/docs/Data-DList.html#v:append
>>
>>
>>
>>
>> https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text.html#v:cons
>>
>> https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text.html#v:append
>>
>> http://hackage.haskell.org/package/vector-0.12.0.3/docs/Data-Vector.html#v:cons
>>
>> https://hackage.haskell.org/package/bytestring-0.10.10.0/docs/Data-ByteString.html#v:cons
>>
>> https://hackage.haskell.org/package/bytestring-0.10.10.0/docs/Data-ByteString.html#v:append
>>
>> Am Mo., 19. Aug. 2019 um 08:16 Uhr schrieb Andreas Abel <[hidden email]>:
>>
>> Helmut, do you actually know the container APIs?
>>
>> Show me cons and append in Data.Set!
>>
>>> On 2019-08-18 19:40, Helmut Schmidt wrote:
>>>
>>>
>>> Am So., 18. Aug. 2019 um 17:17 Uhr schrieb Oliver Charles
>>> <[hidden email] <mailto:[hidden email]>>:
>>>
>>>    On Sun, 18 Aug 2019, 5:47 pm Helmut Schmidt,
>>>    <[hidden email]
>>>    <mailto:[hidden email]>> wrote:
>>>
>>>
>>>        All these philosophical arguments calling for "consistency" with
>>>        the container APIs or that function need words for the human
>>>        mind to comprehend seem short-sighted to me. If we were
>>>        consistent about the proposal itself we'd also demand to add
>>>
>>>           cons = (:)
>>>
>>>           empty = []
>>>
>>>           toList = id
>>>
>>>           fromList = id
>>>
>>>
>>>    I honestly have no problem with any of these.
>>>
>>>
>>> I forgot
>>>
>>>     append = (++)
>>>
>>> We also need to address another elephant in the room... those pesky
>>> tuples and their special privileged non-wordy syntax!
>>>
>>>    pair = (,)
>>>
>>>    triple = (,,)
>>>
>>>    quadruple = (,,,)
>>>
>>>    quituple = (,,,,)
>>>
>>>    sextuple = (,,,,,)
>>>
>>>    septuble = (,,,,,,)
>>>
>>>    octuple = (,,,,,,,)
>>>
>>> If Haskell were invented in this century's EU Haskell source code would
>>> be littered with €s instead of $s but then again I wonder why £ wasn't
>>> picked. But I digress. We can kill two birds with one stone here:
>>>
>>>    apply = ($)
>>>
>>>    strictApply = ($!)
>>>
>>>    compose = (.)
>>>
>>>
>>> It's fun to imagine how code using those definitions would like! But
>>> it's still a -1 for me, sorry!
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> 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

_______________________________________________
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

Kris Nuttycombe
In reply to this post by Sven Panne-2
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
I think the main problem of this discussion (and other similar threads on this list) is that there is no consensus about how to design an API. IMHO, piling up little helpers just because they came up in a few places is a recipe for horrible, bloated APIs. The questions one should ask are "Does it generalize things?", "Does it make my API more powerful?" (i.e. can I do things I couldn't do before), "Does it remove common pitfalls?" etc.  But this is just my personal view, obviously others seem to disagree.... :-/

 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. 

https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#line-972

We define a monomorphic function for this operation, we just hide it in the implementation of the typeclass instance; we do this frequently, intentionally making a monomorphic function inaccessible to the user unless it's called in a polymorphic context (and, if they want to intentionally monomorphise it, require using an extension - type applications - which is particularly ugly/inconvenient for operators like `>>=`.) I think this is unfortunate as a general design choice; the user of a library should have the flexibility to choose, not be forced into one or the other. For [] we have the robot monkey operator, and this is an idiom that people can become familiar with - but it does not appear natively in any documentation; it is a partially applied constructor rather than a top-level function.

My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

Kris

_______________________________________________
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

Tony Morris
In (my) most to least preferred:

* NonEmpty#singleton
* <doesn't exist at all>
* []#singleton


On Fri, Aug 23, 2019 at 3:12 AM Kris Nuttycombe <[hidden email]> wrote:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
I think the main problem of this discussion (and other similar threads on this list) is that there is no consensus about how to design an API. IMHO, piling up little helpers just because they came up in a few places is a recipe for horrible, bloated APIs. The questions one should ask are "Does it generalize things?", "Does it make my API more powerful?" (i.e. can I do things I couldn't do before), "Does it remove common pitfalls?" etc.  But this is just my personal view, obviously others seem to disagree.... :-/

 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. 

https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#line-972

We define a monomorphic function for this operation, we just hide it in the implementation of the typeclass instance; we do this frequently, intentionally making a monomorphic function inaccessible to the user unless it's called in a polymorphic context (and, if they want to intentionally monomorphise it, require using an extension - type applications - which is particularly ugly/inconvenient for operators like `>>=`.) I think this is unfortunate as a general design choice; the user of a library should have the flexibility to choose, not be forced into one or the other. For [] we have the robot monkey operator, and this is an idiom that people can become familiar with - but it does not appear natively in any documentation; it is a partially applied constructor rather than a top-level function.

My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

Kris
_______________________________________________
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

Zemyla
Why hasn't anyone noticed that the singleton function for NonEmpty is just a monkey robot with a mustache? (:|[])

Also, pure works perfectly fine here as well.

On Thu, Aug 22, 2019, 17:52 Tony Morris <[hidden email]> wrote:
In (my) most to least preferred:

* NonEmpty#singleton
* <doesn't exist at all>
* []#singleton


On Fri, Aug 23, 2019 at 3:12 AM Kris Nuttycombe <[hidden email]> wrote:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
I think the main problem of this discussion (and other similar threads on this list) is that there is no consensus about how to design an API. IMHO, piling up little helpers just because they came up in a few places is a recipe for horrible, bloated APIs. The questions one should ask are "Does it generalize things?", "Does it make my API more powerful?" (i.e. can I do things I couldn't do before), "Does it remove common pitfalls?" etc.  But this is just my personal view, obviously others seem to disagree.... :-/

 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. 

https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#line-972

We define a monomorphic function for this operation, we just hide it in the implementation of the typeclass instance; we do this frequently, intentionally making a monomorphic function inaccessible to the user unless it's called in a polymorphic context (and, if they want to intentionally monomorphise it, require using an extension - type applications - which is particularly ugly/inconvenient for operators like `>>=`.) I think this is unfortunate as a general design choice; the user of a library should have the flexibility to choose, not be forced into one or the other. For [] we have the robot monkey operator, and this is an idiom that people can become familiar with - but it does not appear natively in any documentation; it is a partially applied constructor rather than a top-level function.

My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

Kris
_______________________________________________
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 Kris Nuttycombe
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

_______________________________________________
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
It has been two weeks since I submitted this proposal, and one week since the core library committee started deliberating behind closed doors. Is there any visibility into the CLC's process, or at the very least a rough expected timeline?

On Fri, Aug 23, 2019, at 3:57 AM, Sven Panne wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:

On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 

My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

_______________________________________________
Libraries mailing list
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

Keith
In reply to this post by Sven Panne-2
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
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'm still waiting to hear anything at all from the CLC. In the meantime I published the list-singleton library to provide this function: https://taylor.fausak.me/2019/09/07/list-singleton/

On Wed, Aug 28, 2019, at 3:57 PM, Keith wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:

On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 

My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)


Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
Libraries mailing list
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

Edward Kmett-2
In reply to this post by Keith
To grant some insight into what is going on behind closed doors. I figured I'd unpack a bit of it here.

The current resolution is to treat this as step one in a longer maneuver.

We'll be adding singleton to Data.List, immediately.

The headache has really been the issue mentioned above wherein Data.List has historically been treated as an unqualified export that shouldn't clash with the Prelude in any way. 

This is mostly a historical accident and doesn't really match up with the way any of the other "container" like modules are expected to be used. It has led to the somewhat messy state of dozens of other combinators in Data.List such as foldr having to be generalized by the Foldable/Traversable Proposal and other language warts starting to accumulate over time. It is disproportionately difficult to add things to Data.List, so we're going to fix that. -- We'd intended to fix that wart since GHC 7.10, but lacked a sufficient forcing function. Expanding the API of Data.List is acting as that forcing function.

We are going to be switching the usage pattern for Data.List to expect a qualified or explicit import list like Data.Text, Data.ByteString, Data.Set, etc.

This also helps allow for easier expansion of Data.List, which has been pretty stagnant other than a non-report-specified uncons slipping in stealthily in GHC 7.10.

It also helps ameliorate any long term concerns with this taking a name, as it is now something placed in a module where name collisions are okay, as usage is qualified or explicit. Meanwhile, Ryan GL Scott managed to accumulate enough data to show that breakage this one combinator would introduce was pretty minor after all, so we're going to go ahead with adding singleton before the rest of this happens.

To get there, we'll need a slightly longer timeline, and some support from GHC HQ to craft an appropriate warning. This will allow us to monomorphize the combinators in Data.List yielding a sane ending state that doesn't require a PhD in the History of Haskell to fully understand, and we'll be able to retire GHC.OldList once an appropriate 3-release policy compatible migration plan has been fully hammered out.

Normally, I'd wait until we had a full plan with all the migration issues posted rather than shooting off half-cocked like this, but I wanted to be clear about what was causing the communication delay.

-Edward

On Wed, Aug 28, 2019 at 12:57 PM Keith <[hidden email]> wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
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

Helmut Schmidt
Am So., 8. Sept. 2019 um 05:59 Uhr schrieb Edward Kmett <[hidden email]>:
To grant some insight into what is going on behind closed doors. I figured I'd unpack a bit of it here.

Why is it necessary this gets discussed behind closed doors in the first place? Why can't we get more insight into the decision process of such a highly controversial proposal?
 

The current resolution is to treat this as step one in a longer maneuver.

We'll be adding singleton to Data.List, immediately.

The headache has really been the issue mentioned above wherein Data.List has historically been treated as an unqualified export that shouldn't clash with the Prelude in any way. 

This is mostly a historical accident and doesn't really match up with the way any of the other "container" like modules are expected to be used. It has led to the somewhat messy state of dozens of other combinators in Data.List such as foldr having to be generalized by the Foldable/Traversable Proposal and other language warts starting to accumulate over time. It is disproportionately difficult to add things to Data.List, so we're going to fix that. -- We'd intended to fix that wart since GHC 7.10, but lacked a sufficient forcing function. Expanding the API of Data.List is acting as that forcing function.

We are going to be switching the usage pattern for Data.List to expect a qualified or explicit import list like Data.Text, Data.ByteString, Data.Set, etc.

This also helps allow for easier expansion of Data.List, which has been pretty stagnant other than a non-report-specified uncons slipping in stealthily in GHC 7.10.

It also helps ameliorate any long term concerns with this taking a name, as it is now something placed in a module where name collisions are okay, as usage is qualified or explicit. Meanwhile, Ryan GL Scott managed to accumulate enough data to show that breakage this one combinator would introduce was pretty minor after all, so we're going to go ahead with adding singleton before the rest of this happens.

To get there, we'll need a slightly longer timeline, and some support from GHC HQ to craft an appropriate warning. This will allow us to monomorphize the combinators in Data.List yielding a sane ending state that doesn't require a PhD in the History of Haskell to fully understand, and we'll be able to retire GHC.OldList once an appropriate 3-release policy compatible migration plan has been fully hammered out.

Normally, I'd wait until we had a full plan with all the migration issues posted rather than shooting off half-cocked like this, but I wanted to be clear about what was causing the communication delay.

-Edward

On Wed, Aug 28, 2019 at 12:57 PM Keith <[hidden email]> wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
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

Ryan Scott
In reply to this post by Taylor Fausak
> Meanwhile, Ryan GL Scott managed to
> accumulate enough data to show that breakage this one combinator would
> introduce was pretty minor after all, so we're going to go ahead with
> adding singleton before the rest of this happens.

In case you're curious what this data looks like: I compiled GHC
8.6.5, but with the singleton function added to Data.List, and built a
decently large variety of libraries from Hackage to see what would
break. When I was done with this informal experiment, my
~/.cabal/store directory for this version of GHC had 523 entries,
which provides a loose upper bound on the number of libraries that
successfully built (there are some duplicate entries). You can view
these store entries at [1].

Of these ~500 or so libraries, there were a grant total of three that
did not build out of the box:

* blank-canvas-0.7
* ghc-lib-parser-8.8.0.20190723
* pandoc-2.7.3

Of course, this experiment is not exhaustive—there are many other
libraries out there, and there is also lots of code that is not on
Hackage. Nevertheless, the overall percentage of libraries that broke
was surprisingly small, and certainly much smaller than my initial
estimate.

Ryan S.
----
[1] https://gitlab.haskell.org/snippets/1474
_______________________________________________
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

Dan Burton
In reply to this post by Edward Kmett-2
> monomorphize the combinators in Data.List... retire GHC.OldList

Sounds great! Thanks for working on these improvements.

-- Dan Burton


On Sat, Sep 7, 2019 at 10:59 PM Edward Kmett <[hidden email]> wrote:
To grant some insight into what is going on behind closed doors. I figured I'd unpack a bit of it here.

The current resolution is to treat this as step one in a longer maneuver.

We'll be adding singleton to Data.List, immediately.

The headache has really been the issue mentioned above wherein Data.List has historically been treated as an unqualified export that shouldn't clash with the Prelude in any way. 

This is mostly a historical accident and doesn't really match up with the way any of the other "container" like modules are expected to be used. It has led to the somewhat messy state of dozens of other combinators in Data.List such as foldr having to be generalized by the Foldable/Traversable Proposal and other language warts starting to accumulate over time. It is disproportionately difficult to add things to Data.List, so we're going to fix that. -- We'd intended to fix that wart since GHC 7.10, but lacked a sufficient forcing function. Expanding the API of Data.List is acting as that forcing function.

We are going to be switching the usage pattern for Data.List to expect a qualified or explicit import list like Data.Text, Data.ByteString, Data.Set, etc.

This also helps allow for easier expansion of Data.List, which has been pretty stagnant other than a non-report-specified uncons slipping in stealthily in GHC 7.10.

It also helps ameliorate any long term concerns with this taking a name, as it is now something placed in a module where name collisions are okay, as usage is qualified or explicit. Meanwhile, Ryan GL Scott managed to accumulate enough data to show that breakage this one combinator would introduce was pretty minor after all, so we're going to go ahead with adding singleton before the rest of this happens.

To get there, we'll need a slightly longer timeline, and some support from GHC HQ to craft an appropriate warning. This will allow us to monomorphize the combinators in Data.List yielding a sane ending state that doesn't require a PhD in the History of Haskell to fully understand, and we'll be able to retire GHC.OldList once an appropriate 3-release policy compatible migration plan has been fully hammered out.

Normally, I'd wait until we had a full plan with all the migration issues posted rather than shooting off half-cocked like this, but I wanted to be clear about what was causing the communication delay.

-Edward

On Wed, Aug 28, 2019 at 12:57 PM Keith <[hidden email]> wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
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

Elliot Cameron-2
Agreed this an even better outcome than I had hoped for!

On Sun, Sep 8, 2019 at 8:46 PM Dan Burton <[hidden email]> wrote:
> monomorphize the combinators in Data.List... retire GHC.OldList

Sounds great! Thanks for working on these improvements.

-- Dan Burton


On Sat, Sep 7, 2019 at 10:59 PM Edward Kmett <[hidden email]> wrote:
To grant some insight into what is going on behind closed doors. I figured I'd unpack a bit of it here.

The current resolution is to treat this as step one in a longer maneuver.

We'll be adding singleton to Data.List, immediately.

The headache has really been the issue mentioned above wherein Data.List has historically been treated as an unqualified export that shouldn't clash with the Prelude in any way. 

This is mostly a historical accident and doesn't really match up with the way any of the other "container" like modules are expected to be used. It has led to the somewhat messy state of dozens of other combinators in Data.List such as foldr having to be generalized by the Foldable/Traversable Proposal and other language warts starting to accumulate over time. It is disproportionately difficult to add things to Data.List, so we're going to fix that. -- We'd intended to fix that wart since GHC 7.10, but lacked a sufficient forcing function. Expanding the API of Data.List is acting as that forcing function.

We are going to be switching the usage pattern for Data.List to expect a qualified or explicit import list like Data.Text, Data.ByteString, Data.Set, etc.

This also helps allow for easier expansion of Data.List, which has been pretty stagnant other than a non-report-specified uncons slipping in stealthily in GHC 7.10.

It also helps ameliorate any long term concerns with this taking a name, as it is now something placed in a module where name collisions are okay, as usage is qualified or explicit. Meanwhile, Ryan GL Scott managed to accumulate enough data to show that breakage this one combinator would introduce was pretty minor after all, so we're going to go ahead with adding singleton before the rest of this happens.

To get there, we'll need a slightly longer timeline, and some support from GHC HQ to craft an appropriate warning. This will allow us to monomorphize the combinators in Data.List yielding a sane ending state that doesn't require a PhD in the History of Haskell to fully understand, and we'll be able to retire GHC.OldList once an appropriate 3-release policy compatible migration plan has been fully hammered out.

Normally, I'd wait until we had a full plan with all the migration issues posted rather than shooting off half-cocked like this, but I wanted to be clear about what was causing the communication delay.

-Edward

On Wed, Aug 28, 2019 at 12:57 PM Keith <[hidden email]> wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
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

Edward Kmett-2
In reply to this post by Helmut Schmidt
https://groups.google.com/forum/#!forum/haskell-core-libraries should link to the CLC mailing list archive. As far as I can tell it should be public.

-Edward

On Sat, Sep 7, 2019 at 11:53 PM Helmut Schmidt <[hidden email]> wrote:
Am So., 8. Sept. 2019 um 05:59 Uhr schrieb Edward Kmett <[hidden email]>:
To grant some insight into what is going on behind closed doors. I figured I'd unpack a bit of it here.

Why is it necessary this gets discussed behind closed doors in the first place? Why can't we get more insight into the decision process of such a highly controversial proposal?
 

The current resolution is to treat this as step one in a longer maneuver.

We'll be adding singleton to Data.List, immediately.

The headache has really been the issue mentioned above wherein Data.List has historically been treated as an unqualified export that shouldn't clash with the Prelude in any way. 

This is mostly a historical accident and doesn't really match up with the way any of the other "container" like modules are expected to be used. It has led to the somewhat messy state of dozens of other combinators in Data.List such as foldr having to be generalized by the Foldable/Traversable Proposal and other language warts starting to accumulate over time. It is disproportionately difficult to add things to Data.List, so we're going to fix that. -- We'd intended to fix that wart since GHC 7.10, but lacked a sufficient forcing function. Expanding the API of Data.List is acting as that forcing function.

We are going to be switching the usage pattern for Data.List to expect a qualified or explicit import list like Data.Text, Data.ByteString, Data.Set, etc.

This also helps allow for easier expansion of Data.List, which has been pretty stagnant other than a non-report-specified uncons slipping in stealthily in GHC 7.10.

It also helps ameliorate any long term concerns with this taking a name, as it is now something placed in a module where name collisions are okay, as usage is qualified or explicit. Meanwhile, Ryan GL Scott managed to accumulate enough data to show that breakage this one combinator would introduce was pretty minor after all, so we're going to go ahead with adding singleton before the rest of this happens.

To get there, we'll need a slightly longer timeline, and some support from GHC HQ to craft an appropriate warning. This will allow us to monomorphize the combinators in Data.List yielding a sane ending state that doesn't require a PhD in the History of Haskell to fully understand, and we'll be able to retire GHC.OldList once an appropriate 3-release policy compatible migration plan has been fully hammered out.

Normally, I'd wait until we had a full plan with all the migration issues posted rather than shooting off half-cocked like this, but I wanted to be clear about what was causing the communication delay.

-Edward

On Wed, Aug 28, 2019 at 12:57 PM Keith <[hidden email]> wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:
On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 
My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)

Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
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

Taylor Fausak
Hooray! I'm happy to hear that my proposal has been accepted and `singleton` will be added to `Data.List` in the next major release of GHC. I'm also excited about making functions in `Data.List` monomorphic to lists. I look forward to that change!

I'd like to take a moment to thank my team at ITProTV for motivating this proposal. I'd also like to thank the community, both here and elsewhere, for the spirited discussion about this proposal. And finally I'd like to thank the Core Libraries Committee for ultimately decided on this proposal. I appreciate all of you!

Lastly, should I submit a patch for this? I would be happy to, but the code involved is minimal and I don't mind if someone else wants to actually commit it. You can see the code and documentation that I would commit here: https://hackage.haskell.org/package/list-singleton-1.0.0.2/docs/Data-List-Singleton.html#v:singleton

On Sun, Sep 8, 2019, at 10:38 PM, Edward Kmett wrote:
https://groups.google.com/forum/#!forum/haskell-core-libraries should link to the CLC mailing list archive. As far as I can tell it should be public.

-Edward

On Sat, Sep 7, 2019 at 11:53 PM Helmut Schmidt <[hidden email]> wrote:

Am So., 8. Sept. 2019 um 05:59 Uhr schrieb Edward Kmett <[hidden email]>:
To grant some insight into what is going on behind closed doors. I figured I'd unpack a bit of it here.

Why is it necessary this gets discussed behind closed doors in the first place? Why can't we get more insight into the decision process of such a highly controversial proposal?
 

The current resolution is to treat this as step one in a longer maneuver.

We'll be adding singleton to Data.List, immediately.

The headache has really been the issue mentioned above wherein Data.List has historically been treated as an unqualified export that shouldn't clash with the Prelude in any way. 

This is mostly a historical accident and doesn't really match up with the way any of the other "container" like modules are expected to be used. It has led to the somewhat messy state of dozens of other combinators in Data.List such as foldr having to be generalized by the Foldable/Traversable Proposal and other language warts starting to accumulate over time. It is disproportionately difficult to add things to Data.List, so we're going to fix that. -- We'd intended to fix that wart since GHC 7.10, but lacked a sufficient forcing function. Expanding the API of Data.List is acting as that forcing function.

We are going to be switching the usage pattern for Data.List to expect a qualified or explicit import list like Data.Text, Data.ByteString, Data.Set, etc.

This also helps allow for easier expansion of Data.List, which has been pretty stagnant other than a non-report-specified uncons slipping in stealthily in GHC 7.10.


It also helps ameliorate any long term concerns with this taking a name, as it is now something placed in a module where name collisions are okay, as usage is qualified or explicit. Meanwhile, Ryan GL Scott managed to accumulate enough data to show that breakage this one combinator would introduce was pretty minor after all, so we're going to go ahead with adding singleton before the rest of this happens.



To get there, we'll need a slightly longer timeline, and some support from GHC HQ to craft an appropriate warning. This will allow us to monomorphize the combinators in Data.List yielding a sane ending state that doesn't require a PhD in the History of Haskell to fully understand, and we'll be able to retire GHC.OldList once an appropriate 3-release policy compatible migration plan has been fully hammered out.

Normally, I'd wait until we had a full plan with all the migration issues posted rather than shooting off half-cocked like this, but I wanted to be clear about what was causing the communication delay.

-Edward

On Wed, Aug 28, 2019 at 12:57 PM Keith <[hidden email]> wrote:
For what it's worth, when starting out I found the disconnect between list sugar and list constructor/destructors extremely confusing.
In retrospect it seems pretty silly, but I could not figure out how lists were consumed as (x : xs) but often produced with [x, x1, ...]. Mistakes like [x, xs] were common.
When I finally realized that I could construct lists with the list constuctors, I started using them exclusively.

Simplcity and straightforwardness help understanding. It was much easier for me to understand a singleton list as (x : []) than [x]. Having to deal with '(singleton x)' (at the time not knowing the definition of 'singleton') would have been another layer of confusion.

I get that 'singleton' is library design, since in shows up in Map, Array, Set, etc. But for me trying to use lists, it would have only been useful if I defined it myself as a way to learn that constuctors are fuctions, and that 'singleton' means 'single'.

On August 23, 2019 7:56:41 AM UTC, Sven Panne <[hidden email]> wrote:
Am Do., 22. Aug. 2019 um 19:11 Uhr schrieb Kris Nuttycombe <[hidden email]>:

On Thu, Aug 22, 2019 at 3:58 AM Sven Panne <[hidden email]> wrote:
 I think there's a significant difference between "little helper" and "the monomorphic function that is used to implement `pure`" - with a slightly different framing, we might be able to come to an agreement that both the monomorphic an polymorphic versions of this function are useful in different contexts. [...]

I think we can agree that we disagree here. ;-) My brain is too small to remember the names of myriads of trivial helpers, so I very much prefer general, orthogonal things. In our case: If we have a general, polymorphic function (often from a type class), just use that. If for some reason (rarely!) I want a more monomorphic function, I can just add a plain old type signature somewhere (no need for funky language extensions like type applications). This radically reduces the number of things one has to remember. In our case: Know type classes + know a way to make things more monomorphic.
 

My guiding principle for API design is that one should always expose the fundamental building blocks as a low-level API, and then provide a smaller interface for the common use cases. Typeclass instances are no different - they are the general interface that allows us to invoke what is ultimately a monomorphic, low-level building block function in a polymorphic context. 

This is exactly the opposite API design principle I have: Do not expose the monomorphic functions if they are already in a type class. You can easily reconstruct them as a library user via type signtures if this is really needed (still haven't seen many convincing examples of that), but you can' do it the other way round. Less things exposed, no generality/use cases lost => easier to remember.

The thing we can probably agree on: API design is hard and it's not an exact science, more a kind of art which is assessed in a subjective way... :-)


Keith
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
Libraries mailing list
_______________________________________________
Libraries mailing list
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries



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