1. 1

    Not totally related your domain name is really nice! I’m a bit jealous to be totally honest…

    1. 2

      Please think about contributing to lobsters with something different than commercials for your service.

      This parrallel dots spam has to stop, this is not the first user posting this kind of ad, look at the invite tree…

      1. 2

        It can be wonderful when authors submit their pieces, but this blog has been a source of consistently low-quality stories for almost a year. I have sent these users a warning to encourage them to re-evaluate their submissions and consider participating instead of only leaving links.

      1. 2

        Dunno why would someone not just use libSDL in this situation? And then, of course libSDL_grafx, etc.

        1. 10
          SDL2-2.0.7$ cloc src | grep SUM | grep -o '\d\+$'
          bin$ cloc fbclock.c | grep -o '\d\+$'


          1. 9

            I see several reasons, one being education. I had no idea how linux framebuffer system was working before reading this post.

            Great post, thanks for writing it!

          1. 2

            Can somebody explain why is this offtopic or spam?

            [edit] I get it.

            1. 2

              What’d you get?

              1. 2

                This guy’s position on the topic is clearly voiced several times through the podcast.

                I personally disagree with it and don’t really want it do be voiced on lobsters frontpage. I think it makes the community less welcoming.

                However, I ended up watching the entire podcast, it is actually a good technical overview of the problem, political position taken appart… I upvoted it, it doesn’t deserve a negative score.

                Anyways, what I get is that some people are abusing flags to express disagreement instead of commenting for quite some time now; and it’s not something that gonna change anytime soon if no action is taken. Thus asking for explanation is vain.

                1. 2

                  Sorry to hear that. Abuse of flagging on comments is something I’ve grumped about extensively.

                  1. 1

                    I flagged it as off-topic for being only tech-related at two or even 3 removes.

              1. 7

                At that time, when you turned on your computer, you immediately had programming language available. Even in 90’s, there was QBasic installed on almost all PCs. Interpreter and editor in one, so it was very easy to enter the world of programming. Kids could learn it themselves with cheap books and magazines with lot of BASIC program listings. And I think the most important thing - kids were curious about computers. I can see that today, the role of BASIC is taken by Minecraft. I wouldn’t underestimate it as a trigger for a new generation of engineers and developers. Add more physics and more logic into it and it will be excellent playground like BASIC was in 80s.

                1. 5

                  Now we have the raspberry pi, arduino, python, scratch and so many other ways kids can get started.

                  1. 10

                    Right, but at the beginning you have to spend a lot of time more to show kid how to setup everything properly. I admire that it itself is fun, but in 80’s you just turned computer on with one switch and environment was literally READY :)

                    1. 7

                      I think the problem is that back then there was much less competition for kids attention. The biggest draw was TV. TV – that played certain shows on a particular schedule, with lots of re-runs. If there was nothing on, but you had a computer nearby, you could escape and unleash your creativity there.

                      Today – there’s perpetual phones/tablets/computers and mega-society level connectivity. There’s no time during which they can’t find out what their friends are up to.

                      Even for me – to immerse myself in a computer, exploring programming – it’s harder to do than it was ten years ago.

                      1. 5

                        I admire that it itself is fun, but in 80’s you just turned computer on with one switch and environment was literally READY :)

                        We must be using some fairly narrow definition of “the ‘80s”, because this is a seriously rose-tinted description of learning to program at the time. By the late 80’s, with the rise of the Mac and Windows, the only way to learn to program involved buying a commercial compiler.

                        I had to beg for a copy of “Just Enough Pascal” in 1988, which came with a floppy containing a copy of Think’s Lightspeed Pascal compiler, and retailed for the equivalent of $155.

                        Kids these days have it comparatively easy – all the tools are free.

                        1. 1

                          Windows still shipped with QBasic well into the 90s, and Macs shipped with HyperCard. It wasn’t quite one-click hacking, but it was still far more accessible than today.

                        2. 4

                          Just open the web-tools in your browser, you’ll have an already configured javascript development environment.

                          I entirely agree with you on

                          And I think the most important thing - kids were curious about computers.

                          You don’t need to understand how a computer program is made to use it anymore; which is not necessary something bad.

                          1. 4

                            That’s still not the same. kred is saying it was first thing you see with you immediately able to use it. It was also a simple language designed to be easy to learn. Whereas, you have to go out of your way to get to JS development environment on top of learning complex language and concepts. More complexity. More friction. Less uptake.

                            The other issue that’s not addressed enough in these write-ups is that modern platforms have tons of games that treat people as consumers with psychological techniques to keep them addicted. They also build boxes around their mind where they can feel like they’re creating stuff without learning much in useful, reusable skill versus prior generation’s toys. Kids can get the consumer and creator high without doing real creation. So, now they have to ignore that to do the high-friction stuff above to get to the basics of creating that existed for old generation. Most won’t want to do it because it’s not as fun as their apps and games.

                            1. 1

                              There is no shortage of programmers now. We are not facing any issues with not enough kids learning programming.

                              1. 2

                                I didnt say there was a shortage of programmers. I said most kids were learning computers in a way that trained them to be consumers vs creators. You’d have to compare what people do in consumer platforms versus things like Scratch to get an idea of what we’re missing out on.

                        3. 4

                          All of those require a lot more setup than older machines where you flipped a switch and got dropped into a dev environment.

                          The Arduino is useless if you don’t have a project, a computer already configured for development, and electronics breadboarding to talk to it. The Raspberry pi is a weird little circuit board that, until you dismantle your existing computer and hook everything up, can’t do anything–and when you do get it hooked up, you’re greeted with Linux. Python is large and hard to put images to on the screen or make noises with in a few lines of code.

                          Scratch is maybe the closest, but it still has the “what programmers doing education think is simple” problem instead of the “simple tools for programming in a barebones environment that learners can manage”.

                          The field of programming education is broken in this way. It’s a systemic worldview problem.

                          1. 1

                            Those aren’t even close in terms of ease of use.

                            My elementary school circa 1988 had a lab full of these Apple IIe systems, and my recollection (I was about 6 years old at the time, so I may be misremembering) is that by default they booted into a BASIC REPL.

                            Raspberry Pis and Arduinos are fun, but they’re a lot more complex and difficult to work with.

                          2. 3

                            I don’t think kids are less curious today, but it’s important to notice that back then, making a really polished program that felt professional only needed a small amount of comparatively simple work - things like prompting for all your inputs explicitly rather than hard-coding them, and making sure your colored backgrounds were redrawn properly after editing.

                            To make a polished GUI app today is prohibitive in terms of time expenditure and diversity of knowledge needed. The web is a little better, but not by much. So beginners are often left with a feeling that their work is inadequate and not worth sharing. The ones who decide to be okay with that and talk about what they’ve done anyway show remarkable courage - and they’re pretty rare.

                            Also, of course, back then there was no choice of which of the many available on-ramps to start with. You learned the language that came with your computer, and if you got good enough maybe you learned assembly or asked your parents to save up and buy you a compiler. Today, as you say, things like Minecraft are among the options. As common starting points I’d also like to mention Node and PHP, both ecosystems which owe a lot of their popularity to their efforts to reduce the breadth of knowledge needed to build end-to-end systems.

                            But in addition to being good starting points, those ecosystems have something else in common - there are lots of people who viscerally hate them and aren’t shy about saying so. A child just starting out is going to be highly intimidated by that, and feel that they have no way to navigate whether the technical considerations the adults are yelling about are really that important or not. In a past life, I taught middle-school, and it gave me an opportunity to watch young people being pushed away by cultural factors despite their determination to learn. It was really disheartening.

                            Navigating the complicated choices of where to start learning is really challenging, no matter what age you are. But for children, it’s often impossible, or too frightening to try.

                            I agree with what I took to be your main point, that if those of us who learned young care about helping the next generation to follow in our footsteps, we should meet them where they are and make sure to build playgrounds that they can enjoy with or without a technical understanding. But my real prediction is that the cultural factors are going to continue to be a blocker, and programming is unlikely to again be a thing that children have widespread mastery of in the way that it was in the 80s. It’s really very saddening.

                            1. 12

                              I’d prefer it if there was no design. Just the content.

                              1. 16

                                Which you get with a (full) RSS feed.

                                1. 7


                                  Take care if you use hugo, the default rss template does not render the full article.

                                  Here’s a modified one that renders the full article in the feed:

                                  <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
                                      <title>{{ .Title}} </title>
                                      <link>{{ .Permalink }}</link>
                                      <description>Recent posts</description>
                                      <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
                                      <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
                                      <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
                                      <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
                                      <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
                                      <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
                                      {{ with .OutputFormats.Get "RSS" }}
                                          {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
                                      {{ end }}
                                      {{ range .Data.Pages }}
                                        <title>{{ .Title }}</title>
                                        <link>{{ .Permalink }}</link>
                                        <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
                                        {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
                                        <guid>{{ .Permalink }}</guid>
                                        <description>{{ .Content | html }}</description>
                                      {{ end }}

                                  I probably should have included that in the article… Too late now.

                                  1. 3

                                    Why is it too late now?

                                    1. 5

                                      I was about to answer laziness and realized this is not something that should be celebrated.

                                      It’s now included.

                                      1. 1

                                        Thank you for adding it, it will be handy for me when I go back to your post in a few weeks and look for how to do this. :)

                                  2. 1

                                    Blogs should just be an XSLT transform applied to RSS ;)

                                  3. 2

                                    The built-in Firefox Reader mode is a godsend. I feel much more comfortable reading long texts in the same font, page width, background color + the scrollbar on the right now gives me a pretty good estimate of reading time.

                                    1. 1

                                      Weirdly, though, that all comes down to the good design of Firefox reader mode :D.

                                    2. 1

                                      RSS, lightweight versions (light.medium.com/usual/url ?), heck even gopher, perfectly does the job! we need these things.

                                    1. 4

                                      Aha, glad to see more people thinking of replacing prelude, especially Snoyman!

                                      The Foundation project aims towards the same goal, but I guess having a FP-complete backed alternative cannot hurt!

                                      [edit] Right, posted this comment too soon! This is a different approach, they plan to actually reuse the existing libraries. This is definitely nice, hopefully the prelude problem will definitely be fixed in 2~3 years from now.

                                      1. 3

                                        What “Prelude problem” ?

                                        1. 5

                                          The project README more or less states the problem:

                                          The RIO module works as a prelude replacement, providing more functionality and types out of the box than the standard prelude (such as common data types like ByteString and Text), as well as removing common “gotchas”, like partial functions and lazy I/O. The guiding principle here is:

                                          • If something is safe to use in general and has no expected naming conflicts, expose it from RIO
                                          • If something should not always be used, or has naming conflicts, expose it from another module in the RIO. hierarchy.

                                          Snoyman and FP-complete are trying to move Haskell more in the direction of a batteries-included solution for software development. The Haskell Foundation project mentioned by @NinjaTrappeur above is attempting the same thing.

                                          Many of the changes RIO makes as a Prelude replacement solve problems beginners don’t know they have until they’ve been coding a while in Haskell. Using String rather than Text or ByteString is one of the most common mistakes beginners make. And why shouldn’t they? It’s right there in the “base” of the language. And then you learn, often after months of coding, String performance is a disaster.

                                          Whether RIO is the right solution, time will tell. That it’s a step in the right direction, is beyond doubt.

                                          1. 5

                                            I personally use Protolude. The problems it solves (for my projects, on my computer, for my use cases) are:

                                            • head :: [a] -> a becomes head :: [a] -> Maybe a (and all the other partial functions that throw error "message", like tail and so on…)
                                            • everything is Text
                                            • convenience functions that I used to copy in all my project, for example: toS which convert from any string-like (Text, String, ByteString, …) to any other string-like.
                                            • foldl, head, … are on traversable not just lists
                                            • a lot of other stuff, that I’m missing at the top of my head
                                            1. 2

                                              afaik, it’s the issues connected with the standard prelude, either concerning inefficient data structures (String is defined as [Char], ie. a linked list) or simple lack of utilities, which are then afterwards commonly installed by many uses (eg. Data.Vector). Many other “alternative” preludes have tried to replace the standard, but most of them can’t manage to get any significant adoption.

                                              That’s at least what I understand when someone says “Prelude problem”.

                                              1. 2

                                                The Foundation README gives some information about this “problem”, RIO gives other arguments. The two main issues people have with Prelude is partial functions and Lazy IO, as fas as I can tell.

                                                1. 1

                                                  @akpoff, @zge and @lthms pretty much summed up the problem.

                                                  I would also come up with another problem class: “legacy semantics”.

                                                  [EDIT] The following statement is wrong.

                                                  The most notable offender is the Monad typeclass. As it is defined in base (prelude is re-exporting parts of the base library), Applicative is not a superclass of monad. Those two typeclasses are actually completely unrelated as it’s implemented. In other terms, you could end up with a Monad not being an Applicative. Some people are trying to fix that directly in base, some are trying to fix that in external libraries such as Foundation.

                                                  In the end, it is not such of a big deal for an intermediate/experienced developer; however, it is quite confusing for newcomers. Not knowing what you can safely use from the standard library is not a really nice user experience in my opinion.

                                                  [Edit] As a side note, I am saddened to see that the return keyword is preferred over pure. This keyword has a totally different meaning in procedural languages (ie. 90% of the languages), using it in this context is just a constant source of confusion for newcomers…

                                                  1. 1

                                                    Applicative has been a superclass of Monad for quite some time in GHC base. I disagree with the change (breaks compatibility) but understand why they did it.

                                                    1. 1

                                                      Oh yes, you’re right, my bad!

                                                      See monoid and semigroup, the problem is quite similar.

                                              1. 1

                                                Why do we have a science tag if general science is offtopic?

                                                1. 2

                                                  I think not many people read the article to the end.

                                                1. 5

                                                  Great article!

                                                  I have been quite confused at the end though: this website implements an infinite scroll that loads the next article. The design of the page being quite confusing, I was actually reading a completely unrelated article without even noticing the transition.

                                                  That just after reading that over-stimulating System 1 thinking may be a mistake…

                                                  Irony irony…

                                                  1. 1

                                                    Hey @Shashankg22, maybe you could participate to the lobsters community other than posting your own content. Maybe you could share some other articles you enjoy or participate in the comment section?

                                                    As it is, you look like a bot ;)

                                                      1. 6

                                                        Story of Your Llfe and Other Stories is fantastic; I highly recommend it.

                                                        Story of Your Life is the short story on which Arrival was based. I heard the movie did an okay job of adapting it, though I didn’t get a chance to see it. From what I heard they made the story a bit more…fantastical…than the short story.

                                                        1. 2

                                                          The movie did what Hollywood does when it encounters a science fiction story - it dumbed it down, and contorted key plot points in a way that is less than satisfying to those who’ve read the story.

                                                          I honestly don’t know if a straight up screenplay adaptation would actually work though.

                                                          1. 6

                                                            I try to consider film adaptations as completely separate entities. Maybe that’s why I found Arrival thoroughly enjoyable. My favourite sci-fi movie in quite a while. I recently watched it for the second time, and to my surprise it hit me just as hard, perhaps even harder knowing what was coming.

                                                            1. 3

                                                              “I try to consider film adaptations as completely separate entities.”

                                                              BOOM! You and me both. That’s the secret to not getting mad. Just a whole different universe with some superficial similarities. Plus, I judge books and movies with different standards because the mediums are different.

                                                            2. 3

                                                              The screenwriter of the movie explains why he made those changes in this podcast: http://www.theqandapodcast.com/2016/11/arrival-q.html

                                                              Honestly, I love both the book and the movie for different reasons, totally agree with @alva.

                                                              1. 1

                                                                Well, I’m glad it happened because it was one of most interesting and original-feeling movies that year. Guess I should try to read the story sometime, too, if it was even better.

                                                                1. 3

                                                                  I think the movie was great and have read the story, but read it after seeing the movie. It’s not my favorite story in the book. Worth checking out the rest of them too.

                                                                  1. 2

                                                                    Just to be clear - I really enjoyed the movie myself. I didn’t make it clear enough in my post that I was voicing the opinions of other sci-fi fans around me.

                                                                    I look forward to reading the statement from the screenwriter that someone posted to this thread, because there are aspects that really made me wonder why they made the choices they did, but all in all the movie made it possible for the multitudes to get to experience this story which is a win no matter how you slice it.

                                                            1. 3

                                                              Nice share thank you. I want to get started already! And rewrite our main API ;)

                                                              1. 3

                                                                The parser was my favorite. I could be misreading it since I dont know the language. The time example did look really easy to express and/or follow.

                                                                1. 2

                                                                  It is indeed a nice design.

                                                                  You can read more about Parsec in this paper: https://web.archive.org/web/20140528151730/http://legacy.cs.uu.nl/daan/download/parsec/parsec.pdf

                                                                  If you plan to give a try, you should directly start with MegaParsec: https://hackage.haskell.org/package/megaparsec

                                                                  1. 2

                                                                    IMHO, MegaParsec has a terrible roadblock for a Haskell beginner. The first thing you’ll try to do with it will be something like (if you’re lucky enough to get the imports right):

                                                                    import Text.Megaparsec
                                                                    import Text.Megaparsec.Char.Lexer
                                                                    main = parseTest decimal "123"

                                                                    Then you’ll immediately be greeted by a compiler error:

                                                                        • Ambiguous type variable ‘e0’ arising from a use of ‘parseTest’
                                                                          prevents the constraint ‘(ShowErrorComponent
                                                                                                      e0)’ from being solved.

                                                                    For a Haskell beginner, it would be almost impossible to guess what to do next. Well, I’ll give spoilers here:

                                                                    import Data.Void
                                                                    type Parser = Parsec Void String
                                                                    main = parseTest (decimal :: Parser Integer) "123"

                                                                    Normally, you’d rely on tutorials around the net to get you covered, but megaparsec had a recent major release which broke all the tutorials you get by googling “Megaparsec getting started”.

                                                                  2. 1


                                                                1. 3

                                                                  I was curious about VS Code but then read about the privacy policy. It can send your file contents to remote servers. There is a discussion about it here.

                                                                  1. 8

                                                                    As noted in the very thread you linked, that’s only done on crash, and can trivially be disabled if you wish with a toggle in settings. This isn’t meaningfully different from Firefox and Chrome sending memory dumps when they crash. I can see your argument it should be opt-in, and I think I’d agree, but it’s not nefarious.

                                                                    1. 8

                                                                      Well, the meaningful difference is that Firefox prompts before sendig crash reports.

                                                                      1. 6

                                                                        Yup. What @gecko said. Our InfoSec group has blessed it for internal use provided said feature is disabled, and they’re pretty damn hard core about such things. To me if this is your only blocker you should look again.

                                                                        1. 0

                                                                          Considering MS’s history on that topic, I don’t trust them and wouldn’t install it myself.

                                                                          1. 4

                                                                            Don’t trust. Verify. It’s an open source project. Go read the source code yourself, build it yourself, etc. https://github.com/Microsoft/vscode

                                                                            1. 4
                                                                              git clone https://github.com/Microsoft/vscode.git
                                                                              cd vscode && find . -name '*.ts' | xargs wc -l
                                                                              482114 total

                                                                              Be my guest.

                                                                              Not even counting dependencies here. You can’t realistically verify that kind of software by yourself.

                                                                              Even if you manage to read and carefully inspect this codebase (rogue commits tends to be quite hard to spot, you wont spot it with a simple distracted read), you’ll have to still read the ~100 daily commits every day.

                                                                              My point is: nowadays, ultimately, you’ll always rely on trust to some extent when it comes to your security, even when using open source sotware.

                                                                    1. 20

                                                                      Thanks to all the Monad’s tutorial and hype, when I first learned Haskell, a few years ago, it took me a few months to accept that I had understood Monads at the first glance.

                                                                      All those tutorials were just confusing. I was all thinking “what am I missing? it seem so simple! why nobody explains what I’m missing?”. I was missing nothing.

                                                                      A Monad is simply a wrapper. You have a function to wrap a value (return) and a function that applies to the wrapped value another function that returns a different wrapped value (bind). That’s it.

                                                                      1. 11

                                                                        Completely agree with you!

                                                                        See the eightfold path to monad satori from What I Wish I Knew When Learning Haskell:

                                                                        1. Don’t read the monad tutorials.
                                                                        2. No really, don’t read the monad tutorials.
                                                                        3. Learn about Haskell types.
                                                                        4. Learn what a typeclass is.
                                                                        5. Read the Typeclassopedia.
                                                                        6. Read the monad definitions.
                                                                        7. Use monads in real code.
                                                                        8. Don’t write monad-analogy tutorials.
                                                                        1. 2

                                                                          Thanks for this list. Someone on my team recently read and shared a “Monads are like Burritos” blog post. The post made several dubious analogies. The effect was that people felt like they understood Monads. In fact, they did not. This is worse than not understanding them and feeling like you don’t understand them.

                                                                        2. 7

                                                                          Seriously. People act like the concept is so complicated and it really isn’t. I definitely knew what monads were for a long time before all the elaborate metaphors muddled my understanding. So far I’ve gotten the most mileage by illustrating how to convert procedural code to “math style” single expression functions, and rolling from there.

                                                                          1. 1

                                                                            People correct me if I’m wrong because I’m not a Haskeller. I do keep reading these monad things and getting confused about it. One person told me it was basically just imperative programming in a functional language to make things happen in a certain order. I haven’t had anyone attempt to corroborate or refute that. Maybe just one. Your statement sounds similar.

                                                                            It also reminds me of SSA form a little bit in how you describe it.

                                                                            1. 15

                                                                              I will corroborate that as a partial explanation. And it should remind you of SSA form, since it helps accomplish similar things. I think that’s a confusing place to start though, because people tend to ask why functional languages don’t just run things in a certain order anyway. And they do, take printNum( readNum() + 1 ), this will clearly read a number before trying to print the number.

                                                                              Instead, assume we have a VM that only understands simple “math style” functions like:

                                                                              f(x) = expression

                                                                              Such as:

                                                                              square(x) = x * x

                                                                              So yes we could write:

                                                                              main() = printNum( readNum() + 1 )

                                                                              But we could not write:

                                                                              main() = print("multiple"); print("expressions"); print("in a sequence")

                                                                              That is, the VM does not implement multiple statements in a function, it expects only a single expression. Why not? Ignore that for now. This code will work though:

                                                                              main() = printStage1()
                                                                              printStage1() = printStage2(print("multiple"))
                                                                              printStage2(x) = printStage3(print("expressions"))
                                                                              printStage3(x) = print("in a sequence")

                                                                              See how that would work?

                                                                              That’s tedious as hell to write though. Humor me, and now lets write it with lambda expressions. Lambda expressions are function values, i.e. these two definitions of main are equivalent:

                                                                              main() = print("hello world")
                                                                              main = λ() -> print("hello world")

                                                                              Notice I’m using main() = to define a named function, but just main = with lambda. This is exactly identical to the following javascript:

                                                                              function main() { print("hello world"); }
                                                                              main = function() { print("hello world"); }

                                                                              So we can rewrite our program like so:

                                                                              main = printStage1
                                                                              printStage1 = λ() -> printStage2(print("multiple"))
                                                                              printStage2 = λ(_) -> printStage3(print("expressions"))
                                                                              printStage3 = λ(_) -> print("in a sequence")

                                                                              Now lets inline some things, one step at a time:

                                                                              main = λ() -> printStage2(print("multiple"))
                                                                              printStage2 = λ(_) -> printStage3(print("expressions"))
                                                                              printStage3 = λ(_) -> print("in a sequence")
                                                                              main = λ() ->
                                                                                         λ(_) -> printStage3(print("expressions"))
                                                                                       )( print("multiple") )
                                                                              printStage3 = λ(_) -> print("in a sequence")
                                                                              main = λ() ->
                                                                                         λ(_) ->
                                                                                             λ(_) -> print("in a sequence")
                                                                                           )( print("expressions") )
                                                                                       )( print("multiple") )

                                                                              We now have a strategy for compiling a sequence of expressions into a single lambda expression, that returns the result of the last expression. Notice that I used underscores for the lambda args, because their result was unused by the function. But what if our program uses variable names? These are equivalent:

                                                                              main() = {
                                                                                n = readNum();
                                                                              main = λ() ->
                                                                                         λ(n) -> printNum(n)
                                                                                       )( readNum() )

                                                                              Hopefully you can now see that we could write a compiler that converts normal imperative code with variable assignments and so on into an unreadable chain of simple lambdas.

                                                                              So why would you want to do that? Well, if this was a language we were implementing, we can add imperative syntax to our language without actually extending the VM. Our language interpreter can pre-process the code into simple lambdas, then the VM only has to know how to execute simple lambdas. That’s neat.

                                                                              It also lets us make radical simplifying assumptions, just like SSA. Function calls can be evaluated in any order, as long as all its arguments have been evaluated first, just like SSA. But the way we’ve done it so far makes every line dependent on every previous line. So now lets split = into = and <-, where = denotes a weakly ordered assignment, and <- denotes a strongly ordered assignment.

                                                                              main() = {
                                                                                a = 7
                                                                                b = 2
                                                                                x <- readNum()
                                                                                y <- readNum()
                                                                                _ <- printNum(a / x + b / y)

                                                                              We don’t actually need to create a new lambda until we hit a strong assignment. So this simple lambda code is equivalent:

                                                                              main = λ() ->
                                                                                         λ(a, b, x) ->
                                                                                             λ(y) -> printNum(a / x + b / y)
                                                                                           )( readNum() )
                                                                                       )( 1, 2, readNum() )

                                                                              Okay but what if we screwed up and wrote this:

                                                                              main() = {
                                                                                a = 7
                                                                                b = 2
                                                                                x = readNum()
                                                                                y = readNum()
                                                                                printNum(a / x + b / y)

                                                                              Which would compile to this:

                                                                              main = λ() ->
                                                                                         λ(a, b, x, y) -> printNum(a / x + b / y)
                                                                                       )( 1, 2, readNum(), readNum() )

                                                                              If functions can be evaluated in any order, will x or y be read first? It’s undefined. Either readNum() call could run first. You shouldn’t be allowed to weakly order things like IO. That should be an error. One way to do that is to give readNum a type, that insists its return value must be strongly assigned. But readNum should also be ordered with respect to printNum, and anything else that does IO.

                                                                              So lets define these functions with a special return type that says they are both IO:

                                                                              readNum(): IO(Number)
                                                                              printNum(n: Number): IO()

                                                                              This IO wrapper type must be strongly assigned, and the result of its assignment will be its inner type. That is, these are basically equivalent:

                                                                              x: Number = 1
                                                                              x: Number <- IO(1)

                                                                              That’s the IO monad.

                                                                              The strong assignment operator <- is called bind. A monad’s bind function takes a function, and returns a new monad, that represents the result of applying the function to the monad’s inner value. Using our typed readNum and printNum, our program looks like this:

                                                                              main() = {
                                                                                a = 7
                                                                                b = 2
                                                                                  λ(x) -> readNum().bind(
                                                                                    λ(y) -> printNum(a / x + b / y)))()

                                                                              If you’ve ever written node.js before, you might be thinking hey wait a minute, that’s just an IO callback! Honestly yeah, pretty much. But with strong typing and syntax sugar. We can write this:

                                                                              x <- readNum()
                                                                              y <- readNum()
                                                                              printNum(x + y)

                                                                              But if we write this, it’s a type error:

                                                                              x = readNum()
                                                                              y = readNum()
                                                                              printNum(x + y)

                                                                              Why? Because the + operator has the type signature Number + Number, not IO(Number) + IO(Number). Even if + was defined for IO(Number), printNum still takes a Number, not an IO(Number). The type system forces us to bind properly.

                                                                              So now our VM (or compiler) can treat all assignments as weak, because we’ve implemented strong assignments on top of weak assignments and lambdas. Normally assuming all assignments are weak by default would make the language hugely error-prone to use. But the IO functions all return an IO monad, so the type system protects us. Constrast with a conventional imperative language, that must assume all assignments are strong unless it can prove otherwise.

                                                                              Naturally the weak assignment strategy opens up a lot more opportunities for certain kinds of optimization. Haskell still hasn’t taken over the world though, cause there are a lot of other opportunities for optimization, like hand writing vectorized assembly. That kind of thing is harder to do in Haskell than e.g. C.

                                                                              1. 3

                                                                                That’s one of the ways Haskell uses monads, but IIRC (and I probably don’t RC), that’s driven more by Haskell’s lazy evaluation than a fundamental property of functional languages.

                                                                                A more general use case of monads is the Maybe monad, which lets you control for nulls. If a function could return an integer or a null, you instead say its return value is Maybe Int. Then the type system can enforce that anything that calls that function handles both the integer case and the “null” case.

                                                                                1. 2

                                                                                  I do keep reading these monad things and getting confused about it.

                                                                                  Monads are mathematical structures. They have nothing to do with computer programming whatsoever. In fact, monads are so ridiculously general compared to most other mathematical objects that there is no way they could serve a concrete purpose for non-mathematician standards. So the first thing monads are not is “something you use”.

                                                                                  Theoretical computer scientists (read: mathematicians) discovered [0] that you can “give a semantics” to a higher-order [1] strict [2] language in which “types” are denoted by “objects in a category C”, and “a computation that produces a value of type B from a value of type A” is denoted by “an arrow A -> TB”, where T is “a strong monad over C”. The tl;dr of all this [3] is that monads are “something intrinsic to the very structure of the programming languages we use”, just like the Earth’s gravitational field is “something intrinsic to the very structure of the world we live in”. You don’t need a mathematical model for it to exist, although it is nice to have one for some purposes.

                                                                                  However, Haskell is a lazy language, so it is intrinsically comonadic rather than monadic. (Again, [3].) And, while Haskellers like their lazy language overall, they also want the sequential structure of their effects to be more like what strict languages have, because lazy effectful computations are insanely hard to reason about. So you could say Haskellers have monads in their standard library because they don’t have it in their core language.

                                                                                  I have made essentially the same point elsewhere.


                                                                                  [0] As opposed to “created”, like operating systems, word processors or computer games are.

                                                                                  [1] Having procedures as first-class values, e.g., Lisp, Python, Java, ML, Haskell.

                                                                                  [2] Reducing arguments to a normal form before they are passed to a function, e.g., Lisp, Python, Java, ML, but not Haskell.

                                                                                  [3] Lots of details omitted. It doesn’t really matter what any of this means anyway.

                                                                                  1. 1

                                                                                    Your distinction between “discovered” and “created” seems to presuppose Platonism, which is a rather contentious issue in the philosophy of mathematics. A Formalist would say that math is indeed created, and that while the implications of a mathematical system may not be known for a long time, math is still a product of a human mind.

                                                                                    1. 1

                                                                                      I’m by no means a Platonist. I’m just saying monads weren’t invented for this specific purpose. Noticing connections between seemingly unrelated mathematical theories happens all the time.

                                                                              2. 6

                                                                                Explaining monads to programmers is like explaining commutativity to accountants.

                                                                                1. 4

                                                                                  Yep. This is why I shifted to trying to teach people to understand the concept of data that obeys laws. That’s the real issue: they see “monad laws” and they freeze.

                                                                                  1. 7

                                                                                    Probably easier for statically typed OOP people to just hear interface. A monad is a kind of interface for some generic type with a constructor and an aggregate/flatmap where the returned generic is the same type as the input.

                                                                                    I think most of the struggle in learning that its just a type with a bind and return is people worry about teaching the math behind it. This is a bad idea. If you’re going to teach math, teach math, and if you’re going to teach programming teach programming. You don’t need to understand the abstract backbone to understand that you can use this thing to manage side effects.

                                                                                    1. 1

                                                                                      What exactly is a nontrivial data structure, if not “data that obeys laws”?

                                                                                    2. 3

                                                                                      This, a million times over. When I learned about monads in university, the concept was simple and intuitive and I recall just “getting it.” A couple years ago I decided to learn Scala (after a decade of using imperative languages), and a lot of the tutorials made a big deal about monads and tried to explain them in the most obtuse manner, using all kinds of computer science terms and references. For a while I questioned whether I had actually ever understood monads.

                                                                                      1. 1

                                                                                        I’m in the process of learning Haskell myself right now and I feel myself slowly coming to this same conclusion. I think part of the reason they seemed complicated on the surface, for me at least, is due to how heavily they are used in so much Haskell code out there.

                                                                                        Also because of the abstraction-driven nature of Haskell, I’m always aware that there’s (potentially) a lot happening behind a small operator or function so as a beginner I assume there’s a lot of magic happening that I just don’t understand yet. Couple that with terms for these concepts that are rooted in mathematics (and thus unfamiliar with your average dev, like myself) and you get a recipe for assuming there’s always more to understand.

                                                                                        1. 1

                                                                                          I think it really took this video for that to get across to me. This whole time I thought I was still missing something. It turns out I use Monads all the time!

                                                                                        1. 10

                                                                                          Relatedly, if you have linked a Twitter account on your settings page, you will be added to this Twitter list in a few minutes.

                                                                                          If Mastadon has a similar feature, I’d take a PR for it.

                                                                                          1. 3

                                                                                            Groups equivalents (bangs) are available on gnu-social but are sadly not yet implemented on Mastodon.

                                                                                            Related github issue

                                                                                            1. 2

                                                                                              Lists are being implemented though.

                                                                                              1. 1

                                                                                                I agree with Gorgron. Hashtags should be enough. Subscribing to hashtags would be the next logical step.

                                                                                                For everybody in here: Use the #lobsters hashtag ;)

                                                                                                1. 2

                                                                                                  Hashtags don’t really seem usable for this particular case; it’s not as if the people in the Twitter list pushcx made of lobsters users are going to tag every single tweet of theirs with the #lobsters hashtag.

                                                                                                  1. 3

                                                                                                    I honestly don’t see the use in being able to see who uses what websites… is there a more compelling use case for groups/lists?

                                                                                                    1. 3

                                                                                                      Lists are useful on Twitter because I can follow people I know or am interested in generally, and add other more specific accounts to a list. Because I don’t follow them they don’t show up in my main timeline, but I can (for instance) switch to viewing a list-as-timeline for my hometown list (mostly local news + some local businesses) or my “China journos” list (for when I want to see what’s happening with China news). I don’t want to see this content all the time, and I do want it silo’d; thus lists are useful (to me).

                                                                                                      1. 1

                                                                                                        it sounds like you’re using two different notions of list. the ability to view posts from only a certain set of people makes sense, but i don’t see why this couldn’t be implemented in a fashion similar to email clients (which can support any arbitrary filtering you like).

                                                                                                        as for the ability to find people on mastodon who you also know on lobsters, implementing lists as a separate feature on mastodon seems like a poor solution. it still requires lobsters users to add themselves to the list, and there’s the unresolved problem of mapping lobsters id’s to mastodon id’s. the most sensible solution seems to be what people on lobsters already do: list your handles on other sites from your lobsters profile.

                                                                                                    2. 1

                                                                                                      Mass-subscribing and mass-unsubscribing is not a good use case either? Well, I never understood why Twitter lets you subscribe to other peoples lists. Cloning lists would be useful, because then I can mass-subscribe and adapt it to my needs.

                                                                                                    3. 1

                                                                                                      Subscribing to hashtags would be the next logical step.

                                                                                                      Just discovered that this is kind of possible already: Search for the hashtag, then “pin” the column with its settings top right.

                                                                                                1. 4

                                                                                                  Good idea, I was looking to expand a bit my main timeline :)


                                                                                                  1. 2

                                                                                                    I have been using vim wiki to keep this kind of log for the last few months.

                                                                                                    Terrific tool, it supports both internal and external links, most of org mode features, can easily be tracked by your favorite VCS and even has a export to HTML feature.

                                                                                                    1. 1

                                                                                                      Out of curiosity, does anybody use this “framework” in a daily basis here? How long have you been doing that?

                                                                                                      1. 6

                                                                                                        I’m not quite answering your question but hopefully you find it useful:

                                                                                                        I’ve spent the last 3 - 4 years trying to get better at Getting Things Done. I have a few techniques I use:

                                                                                                        • OKRs
                                                                                                        • TODO List
                                                                                                        • Timers

                                                                                                        The way these break down is:

                                                                                                        With OKRs I specify long term goals and how I’ll measure success towards that goal. This works great for work, for home life not so great (turns out my ambitions are a lot bigger than my will when it comes to my personal life) but in both situations they at least give me clear direction.

                                                                                                        With the TODO List I use org-mode, which is great, and work goes it, gets prioritized in it and acted on.

                                                                                                        I user Timers when I’m in crunch/focus period, so not all the time. I use timers in a few, but related, ways. For crunch period, in the morning I’ll plan out my day to the minute with everything I’ll do having a duration with it, including relaxation (but I don’t include bathroom breaks because they are a bit more random). Then I follow the schedule blindly. I can only work on that item during that time period and regardless of if I’m done or not I move onto the next item and work on it for that duration. This is useful in that getting stuck on one item cannot block other items. Also, since I know I’m committed to working on one thing for that time period, I tend to power through blockers. The other use case for timers is more standard Pomodoro where the day is not as tightly scheduled but when I decide to do something I can only do that thing for some duration. This is just a great way to stop watching Netflix or dicking around on the internet because you know when you’ll be back to dick around again (when the timer goes off). For me this works well when I feel I need the extra focus.

                                                                                                        So GTD fits into the third component for me: TODO List. This is also one of my weakest points so I’m moving towards following GTD a bit better. My problem is I’m happy to put work into my todo list and not actually do it. I’m very bad at distinguishing work I really should do from work I’d just like to do. I think GTD will help with this in a few ways:

                                                                                                        • Differentiating between something that is just in the Todo list from Next. Right now everything is equal in my system so it’s really hard to know what I want to do next.
                                                                                                        • More liberally declaring things projects. Right now I only put really big things in my projects bin so larger things that are projects sort of fall between the cracks.
                                                                                                        • Only giving required things a deadline. Right now I’ll say when I’d like something done by and set a deadline and often it slips, so missing a deadline looses all meaning.
                                                                                                        • I have an Incoming list now that is on my phone so I won’t forget as many things. Before I only recorded things I remembered at my computer.
                                                                                                        • The weekly review will be valuable so things can be thrown out and reorganized.

                                                                                                        We’ll see how it goes. Really, the problem I have is lack of motivation to do a lot of things rather than organizing it. But I think some of the tricks in GTD are just to get you to give, even an artificial, sense of urgency to some tasks (like distinguishing Todo from Next as well as making sure every Project always has a Next).

                                                                                                        Hope some of this long comment was useful and thanks for reading.

                                                                                                        1. 1

                                                                                                          Hope some of this long comment was useful and thanks for reading.

                                                                                                          It is! thanks for taking the time writing it.

                                                                                                        2. 2

                                                                                                          I have a basic understanding of GTD (basically on the level described in this blog post) and tried to follow it on several occasions always failing.

                                                                                                          I then started using todoist but didn’t like a third party storing every task item I want to do, hence I went back to taskwarrior which I used in the past.

                                                                                                          Taskwarrior is great but I started missing on-the-go notes so I configured & self-host a taskd sync server and have the taskwarrior app on my Android. After doing this I decided to give GTD yet another but this time ‘proper’ try and ordered the book (it should arrive today) and intend to implement GTD with taskwarrior as outlined in this article

                                                                                                          1. 2

                                                                                                            Been using it for ~10 years consistently, though have been attempting to use it since 2003.

                                                                                                            The only way it really becomes useful is if you have to read your lists to know what to do next. I see a lot of people using it as a “backup” system, which is a lot of work for little gain, IMO.

                                                                                                          1. 12


                                                                                                            • Flaw with the nonce count during the 4-way handshake.
                                                                                                            • Attack on WPA-Supplicant: your WPA2 traffic can be decoded without knowing the preshared key because of the use of a zeroed key as ephemeral key.
                                                                                                            • We just need to patch the clients to prevent that.
                                                                                                            • Most android devices are vulnerable and will probably be never patched.
                                                                                                            1. 5

                                                                                                              I use an always-on VPN on my android. Still waiting for attacks on IPsec…

                                                                                                              1. 2

                                                                                                                Aha, seems to be a pretty good workaround indeed.

                                                                                                                Are you using the built-in client? Do you have any recommendations regarding the VPN configuration?

                                                                                                                1. 4

                                                                                                                  Android’s built-in l2tp/IPsec VPN with OpenBSD and npppd(8) running as a server.

                                                                                                                2. 1

                                                                                                                  I’ve used openvpn and Ciscovpn in the past and really didn’t like the latency component to establishing a connection. What’s your experience with IPsec?