Hi, I tried to draw informal illustrations about Foldable signatures for beginners [1]. I'll also try to draw simple illustrations about new ($).
Of course I like Haskell's beautiful abstraction :) Thank you for your great efforts. [1] http://takenobu-hs.github.io/downloads/type_introduction_illustrated.pdf Regards, Takenobu 2016-02-06 9:09 GMT+09:00 Richard Eisenberg <e...@cis.upenn.edu>: > It may come as a surprise to many of you that I, too, am very worried > about Haskell becoming inaccessible to newcomers. If we can't induct new > people into our ranks, we will die. It is for this reason that I have > always been unhappy with the FTP. But that ship has sailed. > > I fully agree with George's suggestion below that the default Prelude > should be the beginner's Prelude. I believe I have argued this stance in > the past, but louder voices prevailed. Perhaps I was wrong in branding: we > should have a proper Prelude as the default, and make available a super > whiz-bang advanced Prelude as well. I'm never very good about branding. I'd > lend strong support to someone who articulates a concrete move in this > direction, but I don't have the bandwidth to spearhead it myself. > > Despite the various arguments saying that the bits in Java are easier to > understand than the bits in ($), I'm quite unconvinced. (Particularly about > `static`. Even `class` is hard for true beginners.) And the boxed/unboxed > distinction does come up early in Java: just try to write an ArrayList<int> > and now you need to know about boxed types and unboxed ones. > > Chris's point that "it's not about the name" is valid. The Levity --> > RuntimeRep change is not about the name, but about the functionality. > Levity distinguished only between lifted and unlifted; RuntimeRep > distinguishes between boxed/lifted, boxed/unlifted, and all the unboxed > types with their different widths. I'm just clarifying that it's not simply > a cosmetic name-change. > > The old type of ($) was always a lie. -XMagicHash just changes the parser, > allowing the # suffix. It is only by convention that most (all?) unlifted > things end in #. The old type of ($) was perhaps a harmless lie, but a lie > nonetheless. > > Are we comfortable with lying? (Believe me, I'm not trying to impose some > moral dimension to simplifying output!) In my mind, lying about types like > this is in the same space as having a beginner's Prelude. And people will > constantly discover that we're lying and get very confused. Having a whole > host of flags that tell GHC to lie less is somewhat like having two > versions of the language... only the differences manifest only in output > instead of input. > > If we are comfortable with lying in this way: as I've offered, I can hide > the type of ($) (and other representation-polymorphic things) behind a > flag. Easy to do. > > Another great question that has come up is about Haddock output (Hackage). > I think Haddock needs to add a facility where library authors can include > specializations of an overly general type. This can be done in commentary, > but it's not as prominent. Such a new feature would address the ($) > problem, as ($) :: forall (a :: *) (b :: *). (a -> b) -> a -> b is a > specialization of its real type. It would also help a great deal with > FTP-related generalizations. > > I also want to respond directly to Kyle's comments: > > I think its important to identify who you want your "customers" to be. If > you only want the most advanced type theorists to use the language, that is > perfectly fine, but what you lose are thousands of developers that can > benefit the Haskell community without having to know advanced Typing. > > > Rest assured, I want my "customers" to be everyone who wants to program. > I've volunteered to teach a bit of Haskell to high schoolers, and I'd love > a shot at a course where I teach it to people who have never programmed. > > > Needing a "Beginners" mode in a language is *not* a feature, its a > fundamental design flaw. It shows that the language was not sufficiently > thought out and designed for everyone. > > > On an intuitive level, this rings true for me. But when I think about the > details, I'm less convinced. For example, take Scratch (scratch.mit.edu), > which is wonderfully easy to learn and gives kids (and adults!) a great > deal of fun. Yet it's painful to use when you know more. And the Racket > folks have invested a lot of time in coming up with a curriculum to go with > their language, and they explicitly have expertise levels. Needing these > levels may just be part of the game. > > So, rest assured, I remain very receptive to these concerns. And I'd love > concrete help in putting them to rest. > > Richard > > > On Feb 5, 2016, at 6:30 PM, George Colpitts <george.colpi...@gmail.com> > wrote: > > +1 for Christopher's email > Richard, I disagree with "But it could indeed be explained to an > intermediate programmer in another language just learning Haskell." Your > explanation is good but it assumes you have already explained "types of > kind *" and the boxed vs unboxed distinction. Admittedly the latter should > be understood by most Java programmers but I doubt that intermediate > programmers in other languages do. If I did have to explain "$" I would > say, for now think of it in terms of it's pre 8.0 type. Alternatively avoid > mentioning "$" to beginners. I don't believe it is in Hutton's book or any > of Bird's although I might be wrong. > > Most intermediate programmers in another language struggle a lot with > learning monads, witness all the monad tutorials. Absorbing monads is > central, there is a lot that has to be explained before that. Minimizing > that material would be a good thing. > > I have mixed feelings about a beginner's prelude best summarized by saying > the proposed beginner's prelude should be the standard prelude and the > current one should be an advanced prelude. If we have a beginner's prelude > I feel we are saying that this is a hard to understand research language > and we hope that someday you have enough education, energy and tenacity to > get to the point where you understand it. If we do it the other way we are > saying you have what you need but if you want more there is lots! > > On Fri, Feb 5, 2016 at 3:05 PM, Christopher Allen <c...@bitemyapp.com> > wrote: > >> Changing the name doesn't fix the issue. The issue is the noise and the >> referent, not the referrer. There's a habit of over-focusing on names in >> programming communities. I think it'd be a mistake to do that here and risk >> missing the point. >> >> You can make all of the keywords in the Java example salient early on, >> but you cannot make the implementation details you're exposing in the type >> of ($) relevant unless they already have a year or two of Haskell under >> their belts. Listing out the keywords: >> >> 1. public >> >> 2. class >> >> 3. (class name) >> >> 4. static >> >> 5. void >> >> 6. (method name) >> >> 7. (method arguments) >> >> Explaining public, class, static, and void usually happens pretty soon >> after the basics in a Java course. Importantly, they're things you _need_ >> to know to get things done properly in Java. The same is not true of what >> is mentioned in the type of ($). >> >> The implicit prenex form and forall are irrelevant for learners until >> they get to Rank2/RankN which is very much beyond, "I am learning Haskell" >> and into, "I am designing an API in Haskell for other people to use". * vs. >> # is something many working and hobbyist Haskellers I've known will >> scarcely know anything about. >> >> There is a big difference, to my mind, between what is being exposed here >> in Java versus what is being exposed in the type ($). Consider that the >> boxed/unboxed distinction exists in Java but needn't come up in any >> beginner tutorials. >> >> >Types of kind * have values represented by pointers. This is the vast >> majority of data in Haskell, because almost everything in Haskell is boxed. >> >> We can't assume Haskell learners know what pointers are. This, again, >> creates unnecessary noise for learners by forcing exposure to things that >> are irrelevant for a very long time. >> >> >> On Fri, Feb 5, 2016 at 12:13 PM, Richard Eisenberg <e...@cis.upenn.edu> >> wrote: >> >>> Perhaps it will aid the discussion to see that the type of ($) will, for >>> better or worse, be changing again before 8.0. >>> >>> The problem is described in GHC ticket #11471. The details of "why" >>> aren't all that important for this discussion, but the resolution might be. >>> The new (hopefully final!) type of ($) will be: >>> >>> > ($) :: forall (r :: RuntimeRep) (a :: *) (b :: TYPE r). (a -> b) -> a >>> -> b >>> >>> Once again, it's easy enough to tweak the pretty-printer to hide the >>> complexity. But perhaps it's not necessary. The difference as far as this >>> conversation is concerned is that Levity has been renamed to RuntimeRep. I >>> think this is an improvement, because now it's not terribly hard to explain: >>> >>> --- >>> 1. Types of kind * have values represented by pointers. This is the vast >>> majority of data in Haskell, because almost everything in Haskell is boxed. >>> 2. But sometimes, we don't care how a value is represented. In this >>> case, we can be polymorphic in the choice of representation, just like >>> `length` is polymorphic in the choice of list element type. >>> 3. ($) works with functions whose result can have any representation, as >>> succinctly stated in the type. Note that the argument to the function must >>> be boxed, however, because the implementation of ($) must store and pass >>> the argument. It doesn't care at all about the result, though, allowing for >>> representation-polymorphism. >>> >>> In aid of this explanation, we can relate this all to Java. The >>> reference types in Java (e.g., Object, int[], Boolean) are all like types >>> of kind *. The primitive types in Java (int, boolean, char) do not have >>> kind *. Java allows type abstraction (that is, generics) only over the >>> types of kind *. Haskell is more general, allowing abstraction over >>> primitive types via representation polymorphism. >>> --- >>> >>> Could this all be explained to a novice programmer? That would be a >>> struggle. But it could indeed be explained to an intermediate programmer in >>> another language just learning Haskell. >>> >>> For point of comparison, Java is widely used as a teaching language. And >>> yet one of the simplest programs is >>> >>> public class HelloWorld >>> { >>> public static void main(String[] args) >>> { >>> System.out.println("Hello, world!"); >>> } >>> } >>> >>> When I taught Java (I taught high-school full time for 8 years), I would >>> start with something similar to this and have to tell everyone to ignore >>> 90% of what was written. My course never even got to arrays and `static`! >>> That was painful, but everyone survived. This is just to point out that >>> Haskell isn't the only language with this problem. Not to say we shouldn't >>> try to improve! >>> >>> We're in a bit of a bind in all this. We really need the fancy type for >>> ($) so that it can be used in all situations where it is used currently. >>> The old type for ($) was just a plain old lie. Now, at least, we're not >>> lying. So, do we 1) lie, 2) allow the language to grow, or 3) avoid certain >>> growth because it affects how easy the language is to learn? I don't really >>> think anyone is advocating for (3) exactly, but it's hard to have (2) and >>> not make things more complicated -- unless we have a beginners' mode or >>> other features in, say, GHCi that aid learning. As I've said, I'm in full >>> favor of adding these features. >>> >>> Richard >>> >>> On Feb 5, 2016, at 12:55 PM, Kyle Hanson <m...@khanson.io> wrote: >>> >>> I am also happy the discussion was posted here. Although I don't teach >>> Haskell professionally, one of the things I loved to do was show people how >>> simple Haskell really was by inspecting types and slowly putting the puzzle >>> pieces together. >>> >>> Summary of the problem for others: >>> >>> From *Takenobu Tani* >>> >>> Before ghc7.8: >>> >>> Prelude> :t foldr >>> foldr :: (a -> b -> b) -> b -> [a] -> b >>> >>> Prelude> :t ($) >>> ($) :: (a -> b) -> a -> b >>> >>> Beginners should only understand about following: >>> >>> * type variable (polymorphism) >>> >>> >>> After ghc8.0: >>> >>> Prelude> :t foldr >>> foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b >>> >>> Prelude> :t ($) >>> ($) >>> :: forall (w :: GHC.Types.Levity) a (b :: TYPE w). >>> (a -> b) -> a -> b >>> >>> >>> >>> With this change it looks like I will no longer be able to keep `$` in >>> my toolbox since telling a beginner its "magic" goes against what I believe >>> Haskell is good at, being well defined and easy to understand (Not well >>> defined in terms of Types but well defined in terms of ability to precisely >>> and concisely explain and define whats going on). >>> >>> It looks like where the discussion is going is to have these types show >>> by default but eventually have an Alternative prelude for beginners. >>> >>> From *Richard Eisenberg:* >>> >>> - It's interesting that the solution to the two problems Takenobu pulls out >>> below (but others have hinted at in this thread) is by having an alternate >>> Prelude for beginners. I believe that having an alternate beginners' >>> Prelude is becoming essential. I know I'm not the first one to suggest >>> this, but a great many issues that teachers of Haskell have raised with me >>> and posts on this and other lists would be solved by an alternate Prelude >>> for beginners. >>> >>> I don't like the idea of fragmenting Haskell into "beginners" and >>> "advanced" versions. Its hard enough to get people to believe Haskell is >>> easy. If they see that they aren't using the "real" prelude, Haskell will >>> still be this magic black box that is too abstract and difficult to >>> understand. If they have to use a "dumbed down" version of Haskell to >>> learn, its not as compelling. >>> >>> There is something powerful about using the same idiomatic tools as the >>> "big boys" and have the tools still be able to be easy to understand.... by >>> default. Adding complexity to the default Haskell runs the risk of further >>> alienating newcomers to the language who have a misconception that its too >>> hard. >>> >>> Admittedly, I am not well informed of the state of GHC 8.0 development >>> and haven't had time to fully look into the situation. I am very interested >>> to see where this conversation and the default complexity of Haskell goes. >>> >>> -- >>> Kyle >>> >>> >>> On Fri, Feb 5, 2016 at 8:26 AM, Tom Ellis < >>> tom-lists-haskell-cafe-2...@jaguarpaw.co.uk> wrote: >>> >>>> On Fri, Feb 05, 2016 at 05:25:15PM +0100, Johannes Waldmann wrote: >>>> > > What's changed? >>>> > >>>> > I was referring to a discussion on ghc-devs, see >>>> > https://mail.haskell.org/pipermail/ghc-devs/2016-February/011268.html >>>> > and mixed up addresses when replying. >>>> >>>> I'm glad you did, because this is the first I've heard of it! >>>> _______________________________________________ >>>> Haskell-Cafe mailing list >>>> haskell-c...@haskell.org >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>>> >>> >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> haskell-c...@haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> >>> >>> >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs@haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >>> >> >> >> -- >> Chris Allen >> Currently working on http://haskellbook.com >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs@haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >> > > > _______________________________________________ > ghc-devs mailing list > ghc-devs@haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs