Boring Haskell - Haskell

Welcome to the Functional Programming Zulip Chat Archive. You can join the chat here.

James King

Ok so Matt Parson's boring haskell post blew up on the orange site and around twitter. He's also the opening quote in Thinking In Types. I'm curious what has changed his mind about type level programming or how we think this change in tack is going to help with Haskell's adoption?

James King

I've read that before. I'm just trying to understand boring haskell better.

Joel McCracken

so, i have lot of opinions on this

Joel McCracken

I think the thing is that there is a core of haskell that has tremendous value

Joel McCracken

avoiding partial functions, making effects explicit, ADTs etc

Joel McCracken

there are parallel ideas that I think we should be discussing: rebranding "boring haskell" to something like "the haskell golden path", and thinking in terms of "tech radar"

Joel McCracken

another idea is the "haskell pyramid of ideas"

Joel McCracken

this is not limited to haskell though, this phenomenon is common in many areas, but it seems like haskell has its own unique take on it

Joel McCracken

that is, it seems like the haskell community find that there is a moral correctness to type safety

Joel McCracken

more imperative? I don't know

Joel McCracken

this is very similar to the "new shiny" phenomenon in e.g. javascript

Joel McCracken

anyway, we can say that e.g. type level programming has its place, but we wonder if it is worth its weight

Joel McCracken

the big thing i think is that the "haskell golden path" stuff we already have is leaps and bounds beyond what most people have in industry in terms of productivity, safety, and ease of use as a programmer (where ease in this case means the day in and day out of using it, assuming you are already familiar)

Joel McCracken

I have observed that it seems like in the rest of industry, folks have given up on researching how to make maintainable programs, without realizing it

Ryan

IMO boring haskell is largely a thing because of lack of introductory documentation... Stuff like lenses and transformers aren't fundamentally hard concepts, but it's not always straightforward to find guides for them. Once I found good guides, I was able to learn lenses in like...15 minutes? Hardest part is literally just remembering the operators...

James King

Should we be discouraging people from using any of the more advanced features?

Sridhar Ratnakumar

Haskell is not Elm. Let us not discourage people from using advanced features if they are appropriate for the use case. Instead, let us _encourage_ people to use beginner/intermediate features to complete their project.

Sridhar Ratnakumar

As Ryan said above, the main issue I think is introductory documentation.

James King

I've felt that was a missing part too. Sandy started work on a book that may help. I've been thinking that something to follow up Thinking in Types that shows us, through practical projects, how/when to use the more advanced stuff.

Joel McCracken

I mean, i dont know if "discouraging" is the the right word

Joel McCracken

I think the point is to consider the cost/benefit ratio and how using them harms growing the community

Vladimir Ciobanu

I really don't see how me writing "fancy" Haskell in our codebase harms the Haskell community. We hire junior developers (which are assumed to be familiar with Monads) and spend a lot of time training them. I actually really don't understand who's is "boring" Haskell supposed to benefit? Companies that refuse training their junior developers properly?

Vladimir Ciobanu

Or maybe people who want to jump into a Haskell job with very little prior effort? I.e. before at least going through something like the Haskell Book or understanding monads, etc.?

Joel McCracken

i mean, it could be that your job is wonderful and doing all the right things!

Joel McCracken

why do you think there is an absence of jr-intermediate haskell jobs?

Joel McCracken

Or do you disagree with that statement?

Joel McCracken

I don't think "boring haskell" excludes monads, btw. Monads are really a requirement

Joel McCracken

I don't know what it excludes, but what I think personally is a good idea is saying "the community generally finds these things to be on the golden path"\

James King

What is fancy Haskell?

James King

It's an honest question. I hear this debate about boring vs fancy and I'm not sure where I am on this dividing line.

James King

I've recently reduced nearly 1200 lines of manual pattern matching and transformations to 2-300 lines using a library I wrote that makes liberal use of type families, generics, data kinds, etc. The former code was exhausting to read, error prone to maintain and the new code provides type errors and hints if you use it wrong.

James King

I'm presently training people at my company to use Haskell, and it's slow, but I'm confident they will be active contributors and I'm not certain that such advanced features are any more off-putting than monads are to them right now.

James King

Although I am concerned greatly about adoption and the lack of Haskell jobs in general, let alone entry level ones.

Joel McCracken

I think there is a spectrum

Joel McCracken

and/or the pyramaid metaphor is appropriate

Joel McCracken

but its really common in industry to say "for production use you should writing boring code"

James King

I've heard that a lot of course. But I find boring means something different depending on to whom you're speaking.

Joel McCracken

the question I think @James King is your library enough of a black box to be used without worrying about how it is implemented? is the code more flexible or less flexible after those changes?

Joel McCracken

this is kinda why i think a better name would be "golden path" instead of boring

James King

In non-Haskell contexts I've been chastised by senior developers for using map instead of a for loop. The reasoning was that we need to be able to hire anyone off the street and get them situated in our code as quickly as possible. In my 20-ish years of professional programming I don't think I've ever hired anyone off the street. :laughter_tears:

James King

Never the less I think terms may matter in these discussions. It almost follows the similar discussion about which extensions should be included in, "Haskell 2020"

James King

ie: Are type families fancy? Data kinds?

Joel McCracken

I think almost all of these questions are resolvable by saying "does introducing this thing provide significant value"

James King

@Joel McCracken It's necessary to know how to write definitions of type families for a record but you shouldn't need to know the how or the theory behind it. :)

Joel McCracken

in some situations you CANT reasonably resolve a problem without bringing in e.g. lenses

James King

Exactly -- programming is complicated and Haskell has some really nice tools for managing it.

TheMatten

@Joel McCracken or what's the "difficulty-payoff" ratio - because most language features in general do come with their own burden

Joel McCracken

all discussing the same thing

Joel McCracken

I dont think anyone is saying that you should NEVER use those features

Joel McCracken

we are self-selecting as hasekll devs after all!

Joel McCracken

but I think what we ARE saying is that when those features are used, we hope there is a good reason, and generally we'd prefer people to write things that have a higher chance to succeed

TheMatten

Once you reduce that burden, previously awkward solutions may become convenient - as with e.g. Functor interface, which is difficult to introduce in languages without higher-kinded types

Joel McCracken

being honest, some people dont care about their companies at all and just want to play with whatever is interesting to them

Joel McCracken

(this is the extreme though; i dont mean to imply that ANYONE USING TYPE LEVEL PROGRAMMING HATES THEIR COMPANY)

Joel McCracken

i feel like sometimes people forget that haskell is programming and the guidlines for good programming are just... not discussed? like where are the people discussing YAGNI in the context of haskell? KISS? etc

TheMatten

To maybe repeat old point - I can't wait for merge of type and value level in Haskell (aka DependentTypes), because it should make type-level programming as simple as "value-level" one

Joel McCracken

(well i guess to some degree KISS = boring haskell...)

Joel McCracken

that's another facet of the conversation

Joel McCracken

i said somewhere (maybe not here?) that I like the technology radar metaphor

Joel McCracken

a thing can be bad but become awesome

Joel McCracken

a thing for me where this is an issue is that personally i am invested in haskell because I want to make things myself, and I always have to think "do i personally care about this topic" when any haskell thing is discussed

TheMatten

@Joel McCracken Csongor Kiss joined the conversation :big_smile:

Joel McCracken

let KISS = "Keep It Simple Stupid"

Joel McCracken

FWIW i consider boring haskell to be basically everything contained in HPFFP. but the point of these discussions I think are to also discuss what should be included in this idea

Vladimir Ciobanu

I still fail to understand what is it we're talking about. I think the boring haskell manifesto is about defining a subset of libraries and extensions such that it would be easy for beginners to work on projects that adhere to this manifesto.

And I disagree with this, because:
1) I define junior developers as people who are basically on the level of HPFFP, therefore
2) I am confident I can teach somebody who's been through HPFFP how to use lens, servant, generics, and most of the fancy Haskell stuff within weeks (I have, at least twice now)

So I think the focus should instead be on:
a) using the right amount of "fancyness"; I disagree with using these libraries if they're not needed or don't benefit the project
b) being able to train newcomers and junior developers properly (and my blog post elaborates a bit on this)

I also think that we (massively?) over-estimate how hard these concepts are. Especially given a proper environment/resources/good training.

Joel McCracken

so why do you think there are so few jobs for jr developers?

Vladimir Ciobanu

First, there are really few Haskell jobs, period (compared to Java, C#, JS, etc.).

Secondly, I think senior developers and team leaders (people who either ask for openings, or get asked by management questions like "we need to go faster, what do you recommend?") over-estimate how hard it is to learn "fancy" Haskell, assuming a junior developer would take too long to be productive.

Thirdly, even when they do try hiring junior developers, I don't think most places give them a real shot, because:

  • they are not given enough time to accommodate; junior developers need more time than seniors
  • they are not given enough training; I would say that at most every 3 juniors on a team need a different person to help them
  • they are not given enough support; kindness and encouragement goes a long way for a young junior developer
  • often times they are scared to ask some questions because they feel it's something they should know but don't; seniors snap-answering definitely fuels this -- this awful and needs to stop
  • lack of clear tasks, especially the ones that junior developers take on

The codebase(s) I work on right now are high on the fancy scale (also due to the problem domain being rough), and we have three juniors that have 0 professional FP experience before this job (actually, they are all at their first job, or second -- after a relatively short internship). They are all doing great.

Joel McCracken

i will say tho that to me what you are describing sounds rare at the very least

Joel McCracken

If you remove that consideration, then really the concern is "does using this thing provide enough value for its complexity"

Vladimir Ciobanu

Sure, I totally agree with that. Don't use fancy stuff just because you wanna feel smart. But that's now how the Boring Haskell movement reads to me, at all.

Vladimir Ciobanu

It sounds more like: let's use simple Haskell so people who know no Haskell at all can be productive fast, regardless of the consequence. It's exactly success at all cost.

I think the cost is too high, in this case. I'm fine having a limited pool of junior developers to choose from. They need to:

  • go through HPFFP or equivalent
  • be really motivated

I know that's a pretty high entry cost, and the benefits are hard to see up front. OTOH, despite all this, I see this community growing still. At a slow pace, but it looks to me like it's growing. I'm not sure forcing it to go faster is good.

Vladimir Ciobanu

I also have the feeling that a number of companies just don't want juniors because they figure they can afford seniors and they wanna go faster, to which I disagree. I think a few junior developers have a lot to offer to a team, but I'm not sure I can be very eloquent in explaining why. I'll need to think about this for a while.

Joel McCracken

i don't know, as a person who is interested in this movement, i personally do not mean to suggest what you are reading it as

Joel McCracken

For me the biggest concern is that people are generally investing in an unstable base; having those lines clearly delineated helps you know when it makes a lot of sense to branch out

Vladimir Ciobanu

But at a glimpse, I feel a few junior developers can bring a ton of fresh ideas to a project, and their motivation can be infectious.

At my previous job, we had this awesome junior QA who would often times shout "OH MY GOD THIS FEATURE IS SO AWESOME" as he was testing new stuff. It felt the dev team feel so good about what we're doing, because we didn't get to interact with customers at all. This kind of enthusiasm is a lot easier to find in junior devs.

Sridhar Ratnakumar

What we need first and foremost is a decent beginners book (that is not overly verbose) that will get you up to speed writing hobby projects.

James King

I'd like to see a range of such material. I'm currently finishing up @Sandy Maguire 's book and think a nice practical, workbook companion would be a nice addition to it. Sounds like his next book is going to be aimed at practical fundamentals.

Joel McCracken

oh the other thing I wanted to say, I think part of this idea is to show that the basic, simpler stuff is really valuable , and you dont necessarily need to learn all that much to make using haskell worth your while

James King

I've always believed that was true since I was starting out. Aside from understanding the particular features that embody boring vs fancy I also find the dichotomy itself troubling. It implies there is a good and a bad side to be on. I've complained a fair bit about the difficulty curve of Haskell but I think the payoff is worth it and that these things work in a spectrum or continuum instead of a binary.

Joel McCracken

i think "boring" is tongue-in-cheek neg; most people don't like to be bored

Joel McCracken

a thing has to have a name though; can you think of some other name?

James King

I also feel like the Clever Programmer is a boogeyman of our imaginations. I've seen plenty of code in my career and some of it used unnecessary indirection, required tedious setup, and was unpleasant to work with but I've always worked to make that code better rather than blame people. I honestly believe most programmers endeavour to write code that is as simple as possible and no simpler. If you have a team of programmers the code is not created in a vacuum: the organization, the people, the processes... they all affect the outcomes.

A name that reflects the start of a progression, the beginning? Or the layer of the pyramid (I've found that analogy to be quite useful in practice).

James King

In music there are levels, in karate there is kyu and dan :thinking:

James King

In crafts there's progression from lay person, journey person, master, etc

Joel McCracken

but the thing is that many of the "advanced" things are also experimental

Joel McCracken

like, if all the javascript software in the world was rewritten in terms of boring haskell, do you think that code would be better?

James King

Maybe we should adopt a staging system to judge the maturity of various extensions. I've been using some of the "advanced" things in production for a few months now and haven't had any problems.

Joel McCracken

so thats kinda what i meant when I referred to the tech radar thing

Joel McCracken

(i think i mentioned that in here too?)

James King

Ah ok. That makes sense. It seems to work rather well for the Javascript and C++ communities.

Joel McCracken

or you can have things in a pyramid and they are color-coded to indicate maturity

James King

So we are talking about extensions, correct?

Joel McCracken

like i think, where does polysemy fall on the tech radar

Joel McCracken

I wonder if it would be possible to have a community driven tech radar

Joel McCracken

instead of one that is just authored by a specific company

Joel McCracken

or lenses vs prisms; i dont know either, which one is better to learn, assuming i know what problem they solve?

James King

I'd be reluctant to pass judgement on my fellow author's libraries. :sweat_smile:

Joel McCracken

i dont mean to be negative at all about it

Joel McCracken

like ive thought about using polysemy as an example

Joel McCracken

i think sandy is great and support him on patreon

James King

Hackage does have a flag for describing the maturity of a library although, as I understand it, it's self-selected

Joel McCracken

but then there is also like abandonware

James King

Yes, lots. It's a common problem in every software ecosystem but probably felt most heavily in communities such as Haskell's and Common Lisp's where there are so few developers.

Joel McCracken

maybe stackage itself could be a solution?

Joel McCracken

even JS has a TON of it

Joel McCracken

rando npm pkgs that were developed for a short time and abandoned

James King

I'm always looking to other signals for the maturity of a library: adoption metrics, opinions, flags, etc.

Joel McCracken

anyway, i think the two metaphors I prefer are "the haskell golden path" and "the haskell tech radar" or something similar

Sridhar Ratnakumar

I think any of these kinds of software development “manifesto” documents read like a crusade. I’m all for shipping boring simple Haskell code, but I agree a better approach would just be a bunch of “cookbook” style articles demonstrating building simple things with simple Haskell. https://lobste.rs/s/fvjaci/simple_haskell_initiative

Sridhar Ratnakumar

I very much like that idea. Something like typeclasses.com but open source, community maintained and widely available

Sridhar Ratnakumar

The "simple Haskell anxiety"

Less seriously, how can I release the library if I’m now quoted as a strong proponent of using simple Haskell? https://markkarpov.com/post/struggling-to-forget.html

James King

I like the idea of stages and progression. I don't want to get called out every time I use GADTs or type families to solve a problem. :)

Joel McCracken

uhh, where are we getting the idea that this is going to b policed or whatever?

Joel McCracken

I keep seeing it but I have no idea where it comes from

Joel McCracken

like most things, its "opt in"

Vladimir Ciobanu

If anything, I fear this movement will make it so there's less Haskell jobs I would apply to. This is the kind of thing that empowers people who don't understand enough to have an opinion to have one based on reading a 3 minute blog post -- whether it's managers or inexperienced developers.

TheMatten

Plus it's perfect for reactions of type "Haha, you build language so complicated you can't understand it anymore"

toxicafunk

isn't that true of every language though?

TheMatten

@toxicafunk for every language with such movement maybe - I guess C++ could be in similar situation (and it would actually be true in it's case IMHO)

toxicafunk

I mean, like, modern JS is almost unrecognizable compared with one I was writing in 2002

TheMatten

I learned base Haskell in approx. 2-3 years to extent when there's no functionality that would make me surprised - it's the ecosystem where the resulting complexity lies.
And libraries are a matter or choice, so again something like pyramid concept where you choose right tool for your job, with more complex ones useful for more complex tasks.

toxicafunk

and Python 3 has a number of differences from Python 2, etc.
Not that they're particularly hard to learn but.... languages change and may become harder to learn

TheMatten

Though e.g. Python is pretty conservative - language-side features that made it into Python3 from it's release would probably fit one A4, with descriptions

toxicafunk

it got types recently, but I think they're optional

TheMatten

It got "annotations", which got later turned into "strings without quotes" to avoid problems with recursive dependencies, that can be analyzed by external software - they aren't really types and could be used for just about anything

TheMatten

But they're meant to be used with tools like mypy in general

toxicafunk

I wans't aware of the specifics, haven't used python in years
Thx for the explanation

TheMatten

I haven't used it for some time now too, but I was interested in it's quirks at some point :slight_smile:
It's the "putty" of programming languages - you can form it in interesting ways, but it doesn't hold shape well :big_smile:

Sandy Maguire

i am thinking about putting more work into this book of mine

Sandy Maguire

and i think a better community norm than "write boring code" is "write good code"

Sandy Maguire

where good is some metric along the lines of "adequately solves the problem, is robust to bugs, and is the simplest thing that works"

Sandy Maguire

the issue i have with boring code is that what I immediately think of (and the code people show me that counts) seems to be _bad_

Sandy Maguire

in the sense of it's the code you'd write in java. but we _don't want to write java!_

Sandy Maguire

the boring haskell movement seems to be a push back against "let's make an insane abstraction tower just for fun"

Sandy Maguire

which is reasonable, but i think too drastic of a response

TheMatten

@Sandy Maguire
(First, welcome back! :slight_smile:)
Yeah - I guess this "boring" formulation is why people get upset about it - we all want to write good, understandable code and we all agree that premature abstraction doesn't help with that.
It's just that different people have different definition of "boring" in their minds.

Vladimir Ciobanu

Welcome back Sandy :heart:

Yeah, I agree, especially the adequately solves the problem" because some problems are hard and need more "fancyness". However, the boring Haskell movement seems to think all problems are equal and Snoyman even mentioned having a list of blessed language extensions and libraries which is really scary to me.

Sandy Maguire

i spent a few hours brainstorming today about what i think constitutes good, maintainable code

Sandy Maguire

and embarassingly, many of my software projects do not adhere to what i came up with :)

Sandy Maguire

i've got a thai redbull and nothing to do tonight, so going to do some refactoring based on what i came up with, and see if the diff is indeed nicer

TheMatten

I get KISS approach to use of extensions, but I don't get "extension whitelist" - sure, we shouldn't use ImpredicativeTypes (yet), but today, a lot of thought is put into extensions that are added, they aren't "dangerous" - and most of them can be explained in like 2-3 sentences.

TheMatten

@Sandy Maguire btw, we have #Polysemy stream now for "informal discussions" if you're interested :big_smile:

Vladimir Ciobanu

What I don't really like is modules littered with extensions, and those extensions being different module-to-module. I think within a project, people should try to use pretty much the same extensions (it's okay to have a couple of exceptions, like TemplateHaskell declared at the module level) and they should be declared at the cabal/stack level, project-wide.

TheMatten

:100: - except for TemplateHaskell and Undecidable/Ambiguous stuff, I put everything into project configuration

Vladimir Ciobanu

Yeah, that makes it so, despite every project being slightly different, you only really need to think about the Haskell dialect you're using once per project. I would also argue that within an org, it would be beneficial to keep all projects at least close with regards to the extensions used.

TheMatten

I only really differentiate between Haskell2010 and "HaskellX" - at some point I went through GHC manual to get idea about available extensions, and except for some specific ones, they all feel like natural extensions to what Haskell2010 is capable of.

Joel McCracken

Hey Sandy welcome! Glad to see your face again. Hope you are doing ok

Joel McCracken

So for me, as a person seeing "boring haskell" happening, what I really care about is knowing that this or that technology is well understood and is going to actualy provide me benefit vs the cost of using it

Joel McCracken

an example, there was that twitter exchange where i guess someone implemented a business app in relfex and it just did not work out at all

Joel McCracken

(i would like to avoid making such a mistake!)

Joel McCracken

I think the main draw is to help people avoid "rabbit holes" and have more successful (from a business POV) projects.

Joel McCracken

the other thing is, there are a lot of people who I know who are interested in learning haskell, but hestitate to spend so much time learning something that will take so long to see a return. So, having a goal of "learn these things and you can dramatically improve your development experience" I think will be very valuable

Joel McCracken

Like, those of us who want to do haskell are indeed interested in the more advanced/less boring things

Joel McCracken

if not, we wouldn't be here!!

Joel McCracken

i need to write up a blog post

Joel McCracken

FWIW I think GADTs are boring... really they just need a reasonable tutorial

Vladimir Ciobanu

But FRP is also very reasonable in some situations, and if it was missing from the blessed list a lot fewer people would get to learn about it and use it when appropriate.

Also, and please do not take this as a personal attack, but I am really sick of hearing about how much there is to learn. We make absurd amounts of money as programmers compared to a lot of other fields and there's pretty much nothing to hold us accountable. A lot of other lucrative professions require constant learning (doctors, lawyers, etc.) and even taking tests/etc., and I would argue their respective fields don't change nearly as fast as ours.

A lot of us (and I don't mean us in this thread, but programmers in general) are so used to new things taking a 5 minute tutorial to understand that we push back on foreign abstract concepts. "I know C# and I could be productive in Java in a week or two, there must be something wrong with Haskell if I need more than that". This is one of the main reasons I don't even try to convince non-junior developers about the benefits of FP.

Sorry, this became a bit more rant-y than I wanted it to be.

Joel McCracken

I don't take it as a personal attack; again, i am here in haskell because I am interested in learning these things

Joel McCracken

and TBH i agree; the general skill levels of most devs is a shambles

Joel McCracken

Its not even FRP itself, it was using it with GHCJS and the how wildly slow it was.

Sridhar Ratnakumar

I think of Haskell as a ladder, not a flat platform. Books like that of Hutton and Bird gets you to the lower steps, and then we need 'intermediate' writings, like Sandy's book or what https://intermediatehaskell.com/ was going to be in order to the climb the next few steps. On the top exists more advanced concepts. "Boring Haskell" seems like a rationalization to stay on the bottom, instead of recognizing that navigating between the steps is in the same ilk as choosing the right tool for the job (choosing the right abstraction for the job?)

Bolt

Hey Sandy, welcome back! I don't have much to add to this discussion, just wanted to let you know we are all happy you showed your face :D

Sandy Maguire

@Bolt thanks! nice to be here :)

Sandy Maguire

wrt: the topic, i agree with everything above. but, no longer being a professional developer, i feel like i just don't have enough skin in the game on this one to care

Sandy Maguire

hmm. that's a powerful realization.

James King

@Sandy Maguire so good to have you back!

James King

I've been thinking about this, "boring, " stuff a lot lately. It made me wonder what it is about software that makes such a large majority of practitioners afraid of abstractions. I can't imagine starting a project with a math's group and telling everyone, "Ok -- in order to make this project inclusive and maintainable for future mathematicians we're going to stick to plain arithmetic and algebra, nothing fancy and no premature abstractions. We need to make sure that people with very little training will be able to come along and maintain this project when we move on."

I have a lot more to say about this... perhaps in an essay. Let's just say that I'm super concerned about reliability and maintenance as the next person and "boring" software does not have an exclusive stake to reliability and maintenance.

James King

Dichotomies make in groups and I'm always finding myself in the not-in-group. I like fancy Haskell and I don't use it to show off. I've been writing software for 20 years. I'm past that stage of my life.

When it comes to writing maintainable, solid software over the long term I haven't seen any silver bullets. But I will take any tool that makes managing complexity easier, reliable, and convenient.

James King

Make software as simple as possible but no simpler. -- Albert Einstein.

Asad Saeeduddin

I don't want to write fancy Haskell, but given the type system, I usually have no choice

Asad Saeeduddin

There's usually no way of making certain things sufficiently boring, without moving them to an entirely different language or paradigm (e.g. using FFI or writing it using imperative mutation)

Asad Saeeduddin

Or I guess none that I can usually see, maybe that's a learnable skill

James King

There's usually no way of making certain things sufficiently boring, without moving them to an entirely different language or paradigm (e.g. using FFI or writing it using imperative mutation)

What sort of things? And what parts of programs benefit more from this style of programming?

Asad Saeeduddin

An example of a thing is editing parts of a tree. In a "non functional" style this simply involves mutating some parts of the tree. When working with immutable data structures this involves something fancier, e.g. a zipper

Asad Saeeduddin

this isn't because I'm trying to make things fancier, it's just what you end up having to do in order to program in an immutable "functional programming" style

Asad Saeeduddin

The general dilemma isn't a new one either, it's about as old as Haskell itself. In order to ergonomically support IO, the designers had to appeal to the "fancy" concept of programming in a state monad and its Kleisli arrows

Asad Saeeduddin

in a more imperative language you just have an effect and that's it, you don't need to think about how to model more with less

TheMatten

@Asad Saeeduddin functional languages can choose wired-in side-effectful syntax too - nothing would stop Haskell from making IO and do syntax magical - but it's creators decided to provide more flexibility and power by making it specific instance of more general concept

Asad Saeeduddin

@TheMatten Yes, but my point is you then have subroutines instead of functions. While you may call something like JS or ML functional programming, it's less so. The Haskell designers made the choice to do the principled thing and make functions resemble actual mathematical functions, but to actually program in this style requires "fanciness"

James King

I think I see what you're saying. It requires a different thought process and I recall finding it difficult and unusual as well.

Asad Saeeduddin

Of course after a couple years of using Haskell and writing two or three monad tutorials we all forget that we ever considered monads fancy, but the ubiquity of the monad tutorial shows it's still a relatively "fancy" concept

TheMatten

I mean, what's more fancy about (>>=) and pure compared to __iter__, __next__ and StopIteration? Maybe lack of approachable tutorials and interest in underlying concept, instead of an actual interface

Asad Saeeduddin

It's an unfamiliar mathematical concept. We live in a world with time and state, so we all intuitively understand what it means to mutate something. Anyway if you really don't think monads are a fancy concept, just go on to the next thing. Simple changes to a deeply nested data structure

Asad Saeeduddin

To solve this we have optics, but this again is a topic of great fear and confusion. Once you understand it, yes, it's nice and elegant and very useful, better in many ways than the imperative approach even, but I would bet the average programmer finds it easier to grasp how to edit a data structure by mutating it

Asad Saeeduddin

So there's an inescapable hump of fanciness that you have to get over

James King

I find the same effect when teaching developers TLA+ as when I teach the finer points of Haskell: the ability to reason about abstractions is something that is not trained well (and I include myself in that group... it took a lot of time and effort to learn enough about Haskell, TLA+, etc)

Asad Saeeduddin

@James King I had a really hard time understanding how to talk about/understand abstractions too

Asad Saeeduddin

I still do in many ways

James King

Same. I'm in the middle of the abstract algebra course Harvard put online and sheesh... all I can do is throw myself at it in frustration until I realize I can talk fluidly about groups and fields.

James King

It made me stop thinking that anything about programming is, "intuitive." I've come to understand people better by interpreting their use of that word to mean, "familiar."

TheMatten

@Asad Saeeduddin What I meant is that we could've "forgot" about underlying concepts and reduce theory behind interfaces based on them to understandable minimum - but I guess that would cripple their usefulness in many cases - at the end you're probably right...

TheMatten

Thought it seems like every powerful abstraction seems to come with it's own burden of "understanding" required

TheMatten

Not only in FP world

James King

The pyramid seemed like a good way of explaining it... has there been any analysis of open-source Haskell code bases to see how accurate it is? I'd expect the vast majority of Haskell code actually does mostly use pattern matching, guards, ADTs, and type classes vs more "fancy" things like singletons.

James King

(I only mention the abstract algebra course because there was a time when I tackled Haskell's concepts of functors and monoids in much the same manner... everything sounded like gibberish at first)

Fintan Halpenny

I feel like you don't teach abstractions really, you teach particular cases and then _see_ the abstraction/the generality after enough examples

Vladimir Ciobanu

My wife's a professor at the local university. She teaches and does research with (multi-valued) logics, which tends to be very abstract. I recall one of our first interactions/conversations and she was describing what she was working on, and as the good programmer I am, I asked for an example or use case for the thing she was describing, and she had none. Turns out, if you work with abstract ideas a lot, you end up not even needing to consider concrete uses or examples. But of course, it takes a ton of practice.

Vladimir Ciobanu

... and I'm not saying it's necessarily a good thing to abuse. Having examples for abstract ideas is a pretty useful teaching technique. Having good examples is actually quite hard often times. But I wouldn't say that using examples is the only way to learn/understand abstract ideas.

Fintan Halpenny

Hmmm, but does she think of those abstractions with other abstractions? :thinking:

Fintan Halpenny

You gotta wonder, what's the use of an abstraction if it doesn't have a use case :sweat_smile:

Fintan Halpenny

You gotta wonder, what's the use of an abstraction if it doesn't have a use case :sweat_smile:

Fintan Halpenny

My first question is because I tend to think that relating one idea to another is a good way of learning as well. We usually try to analogise or find some kind of common ground so we can access the knowledge a bit easier

Vladimir Ciobanu

I went through that exact same thought process and grilled her on not having examples, but it turns out quite a few mathematicians do this when doing research. There's a ton of papers out there where they do try to come up with an example, and it's usually worse than having no example lol.

Fintan Halpenny

Huh, that's fascinating! :smiley:

Vladimir Ciobanu

... but even then, often case thinking up of examples is an after-thought just to please reviewers because "it's nice to have"

Vladimir Ciobanu

Well, maybe I shouldn't generalize, but that's definitely true for a lot of my wife's collaborator and colleague researchers.

Fintan Halpenny

Ya, I mean it's interesting just to know that that's a thing :)

Sandy Maguire

i'd say most abstract math falls into that category; people make up abstractions and then 40 years later other people come up with uses for them

Sandy Maguire

see quaternions, roots of unity, fermat's little theorem

Sandy Maguire

regarding PROGRAMMING, i'm writing code again for the first time in six weeks

Sandy Maguire

and i have found a very happy level of fanciness

Sandy Maguire

something zen has happened since the last time i wrote _real_ code (as opposed to libraries for people to write libraries)

Sandy Maguire

it's hard to articulate other than "it's doing what i want and i don't have to fight with it and i haven't yet wasted ANY TIME going down stupid rabbit holes (and am about 30 hours in)"

Sandy Maguire

i'm using some of my old libraries from a few years ago... and they're atrocious. but the fixes are all straightforward and delightful

Sandy Maguire

i am not sure how much of this experience generalizes

Sandy Maguire

a lot of my enthusiasm for free monads was seeing the terrible things i saw people do at takt

Sandy Maguire

but it turns out you can just... not do those things. and then "ENFORCE IT AT THE TYPELEVEL" seems less important

Sandy Maguire

maybe those things go out the door when you bring in people you don't super trust....

Sandy Maguire

but it dawns on me that my old "free monads are smart because IO is bad and if you let them, bad programmers will abuse IO everywhere" is just as much of a nanny-state as "we must dumb down all of our code for the babbys we are trying to hire"

Sandy Maguire

the REAL solution, i suspect, is "just don't hire bad programmers"

Sandy Maguire

what's particularly interesting for me is that i'm on my fifth or sixth attempt at making a video game in haskell. with exactly the same tech i've always used. but before i've always gotten bogged down in bad technical decisions i made early on

Sandy Maguire

and that hasn't happened here. i'm curious about whether or not that's just TRYING ENOUGH TIMES that i've learned where all of the dead ends are

Sandy Maguire

or if i've had a qualitative shift in how i approach problems

James King

Why not both? Experience is a messy business.

James King

I think intuition is a very powerful concept to trust because it's our meat computers hashing together the whole messy thing of experience into a vague push.

Sandy Maguire

can you elaborate on that?

James King

Ever get that feeling that you know something to be true or that a particular idea is good?

James King

You don't know why or how you know this

Sandy Maguire

hmmmm... doesn't really resonate

Sandy Maguire

well i guess maybe. i can definitely spot BAD ideas as i'm about to implement them

Sandy Maguire

maybe the secret to writing good code is to not write bad code

James King

It's the theory of creativity that ideas are born from "hunches," the collection of half-baked ideas and experiences

James King

Your brain, a pattern-recognition machine, doesn't always know everything in a material, objective sense but you can sense patterns pretty well. You don't always know that what you're looking at will turn out to be a good idea but you get a good feeling that you've seen this pattern before.

James King

And if you just mash them together, voila!

James King

Sometimes you need to trust that even if you don't know why this is a good idea, but if you see it through, it might turn into one.

James King

Either way you end up learning something new.

Sandy Maguire

hmm.. that really doesn't connect to my experience

James King

Different strokes I guess. :)

Sandy Maguire

i'll pay more attention next time i'm programming and get back to you

James King

I get that a lot -- ideas from different places float around until I get the right mix of them and then, boom! I can't sleep for weeks until it is born.

Sandy Maguire

(lately i've also been coding with -Wall turned on since day one. that is definitely different than my usual projects!)

Sandy Maguire

going back through some older code to see if i can spot the difference

Sandy Maguire

maybe the answer is indeed to be boring

Sandy Maguire

i wrote one typeclass, gave only like 6 instances, haven't touched a GADT or put anything at the type level

Sandy Maguire

though i am happily using libraries which make liberal use of HKDs and GHC generics and fucking magic

James King

I don't believe there is one silver bullet and that the whole range of possibilities should be explored. Mathematics, science, and engineering didn't advance because we decided to stick with what we know, no?

James King

I'm re-reading Expert C Programming on a lark (has been about 10 years or so since the last time) and some of the history of C's development is amazing. I can't imagine it was very boring.

Sandy Maguire

i think boring is the wrong word here

James King

There are anecdotes of language features that were blamed for creating hundred-million dollar craters in Mercury. :)

Sandy Maguire

what @Asad Saeeduddin was saying makes sense to me. i am not trying to do any procedural stuff, and so i am not bolting on any fancy techniques for doing procedural stuff

James King

Well I'm still doing fancy Haskell when it suits because I think you were right that we haven't had enough experience practicing programming in this way, with types, and pushing that to its extreme. Programmers before us had done that, made mistakes along the way, but things moved forward and we're all better for it.

James King

I may never work again but eh.

Sandy Maguire

sorry, don't let me come off as "WE SHOULD NEVER DO ANYTHING FANCY"

Sandy Maguire

i'm just going back through old, failed projects and comparing and contrasting with how i'd do them today

James King

It's not you -- it's the industry as a whole. And the whole crazy enterprise of programming.

Sandy Maguire

eg, check this out:

isSameType
    :: forall (a :: *) (b :: *)
     . (Typeable a, Typeable b)
    => Bool
isSameType = maybe False (const True) $ eqT @a @b

isWidget :: forall a f. IsCommand a => Commanding f -> Bool
isWidget (LocationCommand  (_ :: f b V2))         = isSameType @a @b
isWidget (UnitCommand      (_ :: f b Ent))        = isSameType @a @b
isWidget (InstantCommand   (_ :: f b ()))         = isSameType @a @b
isWidget (PassiveCommand   (_ :: f b ()))         = isSameType @a @b
isWidget (PlacementCommand (_ :: f b (Int, Int))) = isSameType @a @b
isWidget (MenuCommand _)                          = False

this thing is too complicated for whatever it is it's buying me, which i can't come up with after a few minutes of pondering

James King

"boring" software started out far beyond Haskell.

Sandy Maguire

i think the biggest thing i'm noticing in my old projects was _just how much manual state_ i was schlepping around

Sandy Maguire
playerNotWaiting mouse kb = do
  when (mPress mouse buttonLeft) $ do
    modify $ lsSelBox ?~ mPos mouse
  when (mUnpress mouse buttonLeft) $ do
    -- TODO(sandy): finicky
    mp1 <- gets _lsSelBox
    for_ mp1 $ \p1 -> do
      -- TODO(sandy): probably shouldn't unset if you keep your dude in the group
      unsetTT

      lPlayer <- gets _lsPlayer

      modify $ lsSelBox .~ Nothing
      let p2 = mPos mouse
          (tl, br) = canonicalizeV2 p1 p2
Sandy Maguire

the comments are not inspiring

Sandy Maguire

this one is a good case of @Alexis King 's parse, don't validate

Sridhar Ratnakumar

a lot of my enthusiasm for free monads was seeing the terrible things i saw people do at takt

I didn't know takt (formation) used free monads. i do remember shaking my head looking at their singletons code :slight_smile:

Sridhar Ratnakumar

actually i do remember now. they used a type like Has or Member.

Sandy Maguire

@Sridhar Ratnakumar they didn't. they did lots of unprinciped things just doing IO whenever it was convenient

Sridhar Ratnakumar

nice to see that polysemy is inspired by the pain points in real world projects

Sandy Maguire

which lead to an entirely untestable codebase, which lead to us losing a few million $$$ when a big bug came along

Sandy Maguire

i got thinking about free monads when i realized "oh, we are absolutely fucked if we keep this up"

Sandy Maguire

based on nick childer's experiences using them in scala to great effect

Sandy Maguire

i'm having a BLAST here going through old code

Sandy Maguire

my takeaways from this discussion eventually lead to some code i'm _very_ happy with

Sandy Maguire

i'm working on a little IRC client to convince myself I'm not talking shit about how to structure programs

Sandy Maguire

the vast majority of the code turns out to be this:

connectAndGetStreams
    :: ( MonadIRC m
       , MonadFinal m
       )
    => Nick
    -> String
    -> Channel
    -> m ( Stream (Of RecvMsg) m ()
         , Stream (Of String) m b -> m b
         )
    -- ^ A pair of streams of (incoming, outgoing) messages
connectAndGetStreams nick name chan = do
  traverse_ sendIRC $ loginFlow nick name [chan]
  pure
    ( recvMessages
    , flip finally (sendIRC $ QUIT "leaving")
        . S.mapM_ sendIRC
        . S.map (PRIVMSG [RecipientChannel chan])
    )
Sandy Maguire

which you can run directly in IO:

withFreenode :: (Handle -> IO a) -> IO a
withFreenode f =
  runTCPClient "irc.freenode.net" "6667" $ \sock -> do
    irc <- socketToHandle sock ReadWriteMode
    hSetBuffering irc LineBuffering
    f irc

main :: IO ()
main = withFreenode $ \irc -> do
  runApp (Stuff irc) $ do
    (recv, send) <- connectAndGetStreams "helloworld1234" "Sandy" "#irccat"
    void
      . liftIO
      . forkIO
      . runApp (Stuff irc)
      . S.print
      $ recv
    send $ S.fromHandle stdin
Sandy Maguire

or just test the thing:

test :: [String] -> ([RecvMsg], [IRCCommand])
test msgs
      = flip evalState msgs
      . runWriterT @[IRCCommand]
      . improvise (Dicts mockedIRC ignoreFinal)
      $ do
  (recv, send) <- connectAndGetStreams "isovector" "Sandy" "#haskell"
  send $ do
    S.yield "hello"
    S.yield "world"
  S.toList_ recv
Sandy Maguire

this improvise (Dicts thing is SYTC for free

Sandy Maguire

no performance hits to real code, and the scrapped typeclasses only show up in test code

Sandy Maguire
type MockedM = WriterT [IRCCommand] (State [String])

data Dicts =
  Dicts
    (Improvised (MonadIRC MockedM))
    (Improvised (MonadFinal MockedM))
makeImprovCollection ''Dicts

mockedIRC
    :: Improvised (MonadIRC MockedM)
mockedIRC = MonadIRC
  { _sendIRC = tell . pure
  , _recvNewMessage = do
      res <- gets listToMaybe
      modify $ drop 1
      pure res
  }

ignoreFinal :: Improvised (MonadFinal MockedM)
ignoreFinal = MonadFinal
  { _finally = (<*)
  }
TheMatten

@Sandy Maguire I'm starting to like this more and more - though won't it still have problems with optimization on module boundaries?

TheMatten

Or maybe we want specialise pragma on all of them?

Sandy Maguire

no bigger problems than MTL has

Sandy Maguire

the tests are the only bit that SYTC

TheMatten

Yeah - I include mtl in "problematic libs" here :big_smile:

James King

I started off an in-memory kv-store by parameterizing a record of functions on the monad and went to town and it's straight forward, pleasing. I'll pull out a GADT when I need one or Contravariant or Comonad here and there where I need it.

James King

I really liked the Codec post on DerivingVia

James King

But should I be worried about it being too exclusionary to new comers and Haskell adoption? Is it fancy?

Asad Saeeduddin

@TheMatten We can recursively write instances for the instances now, right?

TheMatten

@Asad Saeeduddin Hmm, you mean having Inst method?

TheMatten

Just treat language extensions like libraries. No-one ever complained about a language having too many libraries.

This - in sufficiently advanced language, all those "extensions" could be just "libraries" providing some mixfix macros - one could then simply ask "why aren't you using that library instead of writing this manually?" or "why are we using mixing several libraries and/or custom code for doing the same thing?" or "we're not going to use that library just for the sake of using it, because it's cool"

TheMatten

From this point of view, it's sorta funny that we're okay with huge ecosystem of libraries, where sometimes some of them are doing the same thing, but we treat extensions as some global, fixed set of functionality that should never overlap.
Going further, from this perspective C++'s problem with language complexity sounds like "standard library having many underdocumented and complex APIs for the same thing, with no good guide about which one to select when".

TheMatten

/me just realized that he's basically talking about https://racket-lang.org/ with syntax sugar :sweat_smile: