Escaping Hell with Monads (2017) - <AUTHOR> https://philipnilsson.github.io/Badness10k/escaping-hell-with-monads/ <comment><USER3> What may not be obvious here is that the Haskell function in each of these situations is the exact same generic function. The flow of data is abstracted via the Monad interface, so that it becomes possible to write code that works generically regardless of whether parallelism, IO, databases or whatever else is involved. This makes testing such functions quite pleasant.

<comment><USER4> But is _writing_ such functions, and all the auxiliaries, pleasant as well? What type would I have to give the "getData" function to work in all these examples? What if I just want to call an existing getData function that returns a Maybe, not some generic monad thing? Would I have to tweak the syntax for all the different monads I want to call it from?

Also, what would the print call really look like in actual code? This post talks about composing IO with other monads. I've never seen a monad composition example that wasn't peppered with calls to unintuitively named functions like liftM_.

The pseudocode looks nice, but if the pseudocode isn't a faithful representation of actual use, then it's not very useful.

<comment><USER5> Maybe is already a monad.

<comment><USER4> Yes. That would allow me to use a getData returning a Maybe in the Maybe monad. But I wouldn't be able to use it in the list monad, or the others mentioned in the article.

<comment><USER6> Well, yes.

You will need to convert your type into something else to use in another monad.

As an example, it's common to track failure with an `Either Text` monad, but functions that can fail on a single way usually have an `Maybe a` return type. That means you will probably have an `Text -> Maybe a -> Either Text a` function around and write code like this:

        toEither "Error message" $ functionInMaybe a b

</comment></comment></comment></comment></comment><comment><USER7> Brilliant article. The best way to explain a strange feature like a monad is to list out programming situations to which monads are a good solution.

In the same vein, I finally understood what Lisp macros are for, from a similar article explaining in what programmatic situation you can benefit from writing a macro: [1]

[1] [http://www.defmacro.org/ramblings/lisp.html](http://www.defmacro.org/ramblings/lisp.html)

</comment><comment><USER8> I don't get it. The article doesn't explain anything. It's just a list of statements. "This is bad, that is good." But it doesn't explain why the bad things are bad, and how using monads is better. It also doesn't explain what monads are. "We note that lists are Monads." Why? How did you come to that conclusion?

My guess is that all the people praising this article already "got monads". But for the unenlightened, it doesn't do anything.

<comment><USER9> I don't get it either. These are probably toy examples written to motivate a specific solution. Note that the semantics change between versions. In some versions, erroring out will not print anything, in others it will.

If this is Java, why not use exceptions, or @NonNull. If this is C++, why not use exceptions?

I'll note that for loops and if statements are fundamental constructs that many people don't really understand. I've seen a lot of bad code written with if statements and for loops. If these fundamental constructs can be misused to create bad code, how much likely is it that more abstract constructs like list comprehensions, futures, and monads will be used to create bad code?

<comment><USER10> > Note that the semantics change between versions.

Because each one describes a different type's implementation of the monad interface. The blog post is just trying to illustrate:

"all these problems have the same interface. If we have a general solution to a problem, why use a different ad hoc solution for each?"

<comment><USER9> I think something was missed, and maybe I missed it. It looks to me like this:

        var a = getData();
        if (a != null) {
          var b = getMoreData(a);
          if (b != null) {
             var c = getMoreData(b);
             if (c != null) {
                var d = getEvenMoreData(a, c)
                if (d != null) {
                  print(d);
                }
             }
          }
        }

will only print on non-null, whereas this:

        do
          a <- getData
          b <- getMoreData a
          c <- getMoreData b
          d <- getEvenMoreData a c
          print d

will always print something.

<comment><USER11> >will always print something.

Not necessarily. It depends on which monad is being used here (the article doesn't specify). If you replace the 'print' with 'return' to simplify things, then this could be an expression in the Maybe monad, which would return either (Just d) or Nothing.

The article is lying a bit by suggesting that it's trivial to layer short- circuit-on-error behavior on top of the IO monad. It's possible for sure, but some relatively subtle issues can arise (in Haskell at least).

<comment><USER9> This is what I always hated with C++, and to a lesser extent Java. The code that you cannot see makes it very difficult to understand the code when reading the source. If the only person that can truly understand the code is the author, that is an anti-pattern.

The for loops and if statements were never a problem, it was the default constructors, overloaded operators, and the like that always caused confusion on my teams.

<comment><USER11> In simple cases you'd be able to see the concrete type if this were real Haskell code, so you'd know which monad instance was the relevant one. Your complaint does apply to some uses of the monad transformer library, however.

</comment></comment></comment></comment></comment></comment></comment><comment><USER12> This is a really good way of explaining monads. Generally, when people ask about monads, they're not really asking 'what' monads are - they're asking 'why' and 'how' you use them.

The advantage shown here is that Haskell has special syntax for monads, and this single abstraction can be used for multiple features that many other languages have specialised syntax for.

<comment><USER13> That can also be seen as a disadvantage. There is value to having different things look different.

<comment><USER14> The difference is given by the code context (which is unfortunately entirely missing from the article). What's shown here are the things all these patterns have _in common_. The whole point of abstraction is to have different, but related, things look the same.

Haskell (and these examples) certainly raise the level of abstraction to extremes (compared to other languages). But as long as the context (explicit type annotations, if necessary) make it clear what the code does, I don't see this (even conceivably) as a disadvantage.

<comment><USER15> > But as long as the context (explicit type annotations, if necessary) make it > clear what the code does, I don't see this (even conceivably) as a > disadvantage.

I spent 3 years trying to learn Haskell, and I never found this clear. When you see a "do" block, where do you look to figure out what it's actually doing?

<comment><USER16> > When you see a "do" block, where do you look to figure out what it's > actually doing?

If you need to know, you look at what consumes the result. If it's abstract (say it's a top level binding `... -> m a` where the m is abstract) you don't _need_ to know "what it is actually doing" \- it should be correct for any choice of `m`.

Whether this stuff is easy to find/follow certainly depends on the quality of the code, as well as your experience. It's not something I struggle with, working day-to-day in Haskell.

<comment><USER17> > you don't need to know "what it is actually doing" \- it should be correct > for any choice of `m`.

I don't know what it's doing, but it's correct. :-/

So _what_ is it doing that's correct? Or is it some abstract correctness?

<comment><USER16> It's not abstract correctness, it's satisfying contracts up to an interface.

Take `sequence :: Monad m => [m a] -> m [a]`

That takes a list of actions and gives us an action that runs each in turn and collects the results in order. The correctness _relative to that description_ is clear regardless of whether each input action is threading state or handling failure or printing to the screen.

<comment><USER17> Then this clearly doesn't answer the original question, does it?

<comment><USER16> Not on its own. Fortunately, it wasn't the entirety of my answer to the original question. When you're writing something like `sequence`, you don't need to know the implementation of the interface you're working against. As you get comfortable in Haskell, more things are "like `sequence`". There will always be things that aren't - for those, as I said, you should look where the value is consumed. And as I neglected to say, you can always add a type annotation when things get unclear.

<comment><USER17> Ah, the old Java adage: any abstraction can be solved with many more layers of abstraction.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER18> The way I often explain it to a C++ developer is by asking this question: "what if the semi-colon was merely an operator, that you can overload?"

Then they sort of start to see the power.

<comment><USER19> How would you overload that for getting something monadic-like? Is there a simple example (C++ is obviously not my native tongue)?

<comment><USER18> well the (;) is the `bind. The problem with the question is that it only works on a conceptual level as C++ does not have type system support for statements. (ie, in {a;b} what's the type of a ?)

But, it allows them to see how you could build fiber/promises/lightweight_threads support using this concept, which is most of the times what they are interested in anyway.

<comment><USER20> I never thought about shifting perspective on the semicolon from imperative to function. I'll have to revisit the idea after I learn functional programming. For now, maybe what you describe could be possible with tools that do C++ metaprogramming in Haskell or Racket like below. I liked what I was reading despite not even using those languages. ;)

[http://aszt.inf.elte.hu/~gsd/s/cikkek/abel/haskelltmp.pdf](http://aszt.inf.elte.hu/~gsd/s/cikkek/abel/haskelltmp.pdf)

[http://matt.might.net/papers/ballantyne2014metameta.pdf](http://matt.might.net/papers/ballantyne2014metameta.pdf)

</comment></comment></comment></comment><comment><USER21> All the ad hoc solutions look at least as clear if not clearer than their monad equivalents.

Also, that article conveniently ignores that as soon as you start mixing monads, you enter a different kind of hell: monad transformer hell.

Because you see, monads don't compose. Not without these transformers. And if you think the monad examples in that article were hard to follow, wait until you see monad transformers in action.

Also, I don't think replacing a `for` loop with a `for` comprehension is that much of a gain. I'll pick a `map`/`filter`/... any day over such `for` loops.

<comment><USER22> I worked on a Scala system with two rookie Scala programmers who had been taught that `for` expressions were a simple and easy way of composing futures, because it was the monadic way. The code looked very neat, but we had an epidemic of swallowed Failures, and the ones that weren't swallowed were often interpreted incorrectly. (For example, a 500 from service A would be logged as a 500 from service B, because someone miscalculated how the Futures and Trys were being composed.) This was due to people not understanding the for expressions they were writing. Rather, I seemed to be the only one _trying_ to understand the `for` expressions: I often had to mentally (or even manually) translate them into flatmaps and maps according to the language spec to discover that they were not doing what the person who wrote them intended. The other programmers, who had been promised that `for` expressions were obvious and self-explanatory, felt that this should be unnecessary, and that if they were making mistakes, then Scala was failing to live up to its billing, and we should stop using it. It was extremely frustrating. I love Scala, and I feel that promoting `for` expressions to beginners like that was ideologically motivated and bad for the language.

It's much easier to just use map and flatMap. But that won't do, because the virtue of monads is supposedly the abstractions built on top of them.

<comment><USER23> What was your solution with the rookies ? Keep the for expression and fixing bugs, or rewriting them more explicitly ?

<comment><USER22> A little bit of both. I kept hoping something would click and I would end up loving the for expressions, but for a few monsters that I could only untangle by translating the code line by line into map, flatMap, and filter, I committed the translations so I would never have to do that again. Neither of the other programmers is writing Scala anymore. I've mostly steered clear of for expressions since then.

</comment></comment></comment></comment><comment><USER24> Few nits with this:

1\. This seems like an article about Haskell's do-notation, not Monads. The article even decries Promises, which _are_ Monads.

2\. "Call you language implementor and ask for do-notation today!" isn't very satisfying. I would be curious to read such a proposal for eg; JS, though it would need another name (do-expressions already have a proposal). Meanwhile, it might have been helpful to show how to implement these Monads in a common tongue (eg; JS).

3\. The article did not display the bodies (or even type signatures) of the functions at hand. It's unclear to a reader unfamiliar with Haskell whether they are all the same, and what interface they must conform to.

4\. The examples listed as "Hell" don't sound like hell to me. They're minor annoyances that I run into occasionally. The code listed as "problematic" isn't blissful to write and doesn't feel elegant, but is universally easy to write and read.

As an aside, it feels like Go and Haskell would be at opposite ends of some spectrum (obvious vs elegant?). In almost any business/production setting, I would choose the former.

<comment><AUTHOR> >do-expressions already have a proposal

For those who are curious, it's this one: [https://github.com/tc39/proposal- do-expressions](https://github.com/tc39/proposal-do-expressions).

</comment></comment><comment><USER25> So, the only problem here is none of the examples actually handle the errors. Chains of partial functions, using any language I've ever tried, are easy when you don't have to do anything about the null value. The article demonstrates this in multiple languages. In practice, the hell only starts when you have to send control flow somewhere else or show the user a different response for every failed partial. I haven't used monads intentionally, can they do anything special about the real world case of having to handle every error separately?

<comment><USER26> People would use something like an Either monad in that case (in real code they may use an Error monad). If all your getData functions have a return type `Either MyError GoodResult` then you could write something like:

      data MyError = MyFirstError | MySecondError

      type GoodResult = String

      myFunc =
        case doEither of
          Right x -> *handle good result*
          Left MyFirstError -> *handle error*
          Left MySecondError -> *handle error*
        where
          doEither = do
            a <- getData
            b <- getMoreData a
            c <- getMoreData b
            d <- getEvenMoreData a c
            return d

If one of those functions returns a "Left" (or error) value, the remaining functions are not evaluated. If they all return a "Right" value, doEither evaluates to a successful "Right" value.

This works much better when all of your functions fail in the same way. If some functions fail with an empty Maybe and some fail with an Either and some with Error you will have to wrap all of those to take advantage of do- notation.

<comment><USER21> Please don't use Either to carry errors, it's really silly to use a language with a strong type system and then rely on convention to represent the error on the correct side of the monad.

Is error left or right again?

That's right, you shouldn't have to remember.

Use a more specific type for this, some GADT with clearly named instances (e.g. "Error" and "Value").

<comment><USER27> Right is the right result and Left is the wrong result. That's about as easy it gets when it comes to remembering things. There is already a strong convention for using Either for this purpose and it's built into the standard library, since the Monad instance is designed to allow you to do this.

If you create your own data type for this, you are designing yourself into the Monad transformer hell you mention in another comment.

<comment><USER21> > That's about as easy it gets when it comes to remembering things

I use a statically typed language so I have fewer things to remember because the compiler does the bookkeeping for me.

`Either` is a generic variant record, it should not be used to carry errors.

And as a general rule, any programming construct that relies on convention instead of static typing is prone to generating bugs.

<comment><USER27> > `Either` is a generic variant record, it should not be used to carry errors.

The name suggests that, but the Monad instance suggests that Either is an asymmetric data type, where the left and right branches carry different meaning.

> And as a general rule, any programming construct that relies on convention > instead of static typing is prone to generating bugs.

If the Either branches were named `Error` and `Success`, using `Error` to carry errors would be just as much of a convention as using `Left` for that purpose (a more sensible convention, but nonetheless a convention). The only way you'd get around that is if you'd somehow encode in the language what is and what isn't an error and use that to statically force correct branch usage.

</comment></comment></comment></comment></comment></comment><comment><USER28> I'd like to point out that do-notation in Haskell is a syntax sugar for something nasty.

Let's look at the example:

        do
          a <- getData
          b <- getMoreData a
          c <- getMoreData b
          d <- getEvenMoreData a c
          print d

This desugars to:

       bind getData (
           bind (\a -> getMoreData a) (
           bind (\b -> getMoreData b) (
           bind (\c -> getEvenMoreData a c)
           \d -> print d)))

_Edit_ : the above code was initially wrongly desugared.

Which is exactly the callback hell criticized in the article.

Sure, monads and do-syntax provide a nice abstraction and are interesting constructs from the perspective of type theory, but in my opinion it's not principally better than Promises or await.

<comment><USER29> `bind` is usually written as `>>=` in Haskell.

Haskell also lets you write simply

        print

instead of

        \d -> print d

I wouldn't consider this part syntactic sugar – if one did, I suppose one would have to say that

        f(g())

in Python is sugar for

        (lambda i: f(i))((lambda: g())())

Here's how the desugared version looks in more idiomatic Haskell:

        getData
          >>= \a -> getMoreData a
          >>= getMoreData
          >>= getEvenMoreData a
          >>= print

(where I kept the lambda around the first getMoreData since `a` was used in getEvenMoreData)

</comment></comment><comment><USER30> This is probably the most concise and elegant justification for the monad pattern that I've seen. And I've seen _many_.

</comment><comment><USER31> I'm not sure why

      do
        a <- getData
        b <- getMoreData a
        c <- getMoreData b
        d <- getEvenMoreData a c
        print d

is better than

      var a = getData();
      var b = a?.getMoreData();
      var c = b?.getMoreData();
      var d = c?.getEvenMoreData(a);
      print(d);

Other than the "var" at the start of each line they look like they take up about the same amount space, and the pattern is near-identical, so they're equally readable.

<comment><USER32> The point is not that any one example is better than the other, rather it's that the same syntax can be used to uniformly solve multiple different problems (partiality, async, "non-determinism", and state-passing).

<comment><USER15> One thing this article doesn't really make clear is how someone reading the code can actually determine which of these things is being done. Code that looks the same but magically does something different doesn't seem like an improvement to anyone who wants to be able to maintain their code.

I know enough Haskell to know that the "magic" comes from which instance of Monad is being used, but between the weirdness of overloaded values, the fact that the "do" syntax doesn't really make it obvious which value is the important one, and Haskell programmers' aversion to using parens, I still find this stuff impossibly hard to read. This is largely why I gave up on Haskell after trying to learn it for 3 years.

<comment><USER6> Well, the `do` syntax makes it patently obvious what is the important value, it is the one being assigned into variables within the block and used as argument of functions. It hides the not so useful one that is the name of the monad you are using.

You know the kind of "magic" by looking at the type declaration on the line just above that `do`. If there's no type declaration there, I hope the code is simple enough that it is self explanatory, otherwise it's plain bad code.

Things are made more complex when the monad type is generic. But then, this just makes it patently visible that the monad does not matter at all and the code must work as intended on any kind of "magic" you can throw at it.

About the aversion to using parens, matched operators make your code brittle and hard to change. This is not obvious if you have never seen any other way of organizing code, but it is a large effect.

<comment><USER15> > the `do` syntax makes it patently obvious what is the important value

Given that it seems that the majority of people who attempt to learn Haskell end up giving up, I'd argue that very little about it is "patently obvious".

> it is the one being assigned into variables within the block and used as > argument of functions

I think this is part of what confounds me when it comes to Haskell (aside from the terrible syntax and horrible coding conventions): when I'm reading an expression I understand the overall expression by understanding what the sub- expressions do. That is, I can start at the leaves of the expression tree and work my way up to the root.

In Haskell, sometimes this is not possible, because sometimes the type of the subexpression is constrained by something higher up in the AST. This leaves me not knowing where to start with trying to decipher the type of an expression.

> About the aversion to using parens, matched operators make your code brittle > and hard to change. This is not obvious if you have never seen any other way > of organizing code, but it is a large effect.

What are "matched operators"?

The aversion to using parens means that I can't even parse code unless I know the fixity rules of all of the operators in an expression. I'm sure you'll say this is easy to pick up after a while, but that has not been my experience.

<comment><USER6> > In Haskell, sometimes this is not possible, because sometimes the type of > the subexpression is constrained by something higher up in the AST.

The point is that this constraint always have the exact same format. It may have some different semantics, but Haskell makes you abstract over those to get into the operational function, while the compiler verifies anything that isn't local operations to fit your overall structure.

Really, learning Haskell is the process of learning to abstract semantics away from your code. It's a hard process, it's not something natural.

> What are "matched operators"?

Those are operators that require a matching. Usually parenthesis, square brackets and braces. Haskell has the unmatched operators `.` and `$` that people use instead, and for reading it you do have to understand their priority. Most operators do not a set fixity, but those two are a must.

<comment><USER15> > > In Haskell, sometimes this is not possible, because sometimes the type of > the subexpression is constrained by something higher up in the AST.

> The point is that this constraint always have the exact same format.

I'm not sure how to even parse that sentence. Let me phrase as a question: when trying to understand a given piece of code, how can I determine the type of an expression when its type is someone determined by its sub-expressions (like virtually any other typed language), but sometimes is determined by what consumes it?

The way people can deal with the complex is by decomposing them into smaller parts, understanding those, and then composing that to understand the whole. It seems that in Haskell you are required to understand the whole thing at once, because you can't reliably determine the type of a sub-expression out of context.

> > What are "matched operators"?

> Those are operators that require a matching. Usually parenthesis, square > brackets and braces.

And how do "matched operators" make code more brittle and harder to maintain?

I think the opposite is true: to maintain code you must first be able to read it, and what you call "matched operators" are far superior for readability compared to having to remember fixity rules. Even after 3 years of dealing with Haskell I found myself constantly misreading code because I didn't get the fixity right.

<comment><USER33> Could you please give a concrete example? The majority of Haskell expressions have what is called a "principal type". The type of such an expression is independent of its subexpressions or super- expressions.

<comment><USER15> A concrete example of what?

<comment><USER33> A concrete example of an expression that you have difficulty determining the type of.

<comment><USER15> It's been a few years since I gave up on Haskell, but I remember anything involving `do` (especially containing a `return`) or `sequence` seemed to require a lot of guesswork about what type was involved. Pretty much anything where the type of a subexpression would be an overloaded type has a high potential for being confusing.

Another example of what I'm talking about is the fact that even the expression "5 == 5" gives an error unless the kludgy type defaults are enabled. The fact that they felt the need to add type defaults and MR to the language is a pretty strong sign that they screwed up the usability of the type system.

<comment><USER33> Haskellers would tell you that what they appreciate about this is that you don't have to understand sequence and return! They do the "same thing" for all monads in the sense that they obey well-defined laws.

"5 == 5" is a different issue, and ironically is ambiguous because it's so simple. Most practical arithmetic expressions would have some way of disambiguating the type.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER34> You can flatten the pyramids with logical AND-gates. Eg. it only continues if it's successful. Here's an example:

      var a = getData();
      if (a == null) return null;

      var b = getMoreData(a);
      if (b == null) return null;

      var c = getMoreData(b);
      if (c == null) return null;

      var d = getEvenMoreData(a, c)
      if (d == null) return null;

      print(d);

For async code I use counters. But async code is usually thick, not because lack of abstraction, but because you _do not want any loose ends_ eg. you want to handle all and every exception that might arise. As well as having code for abortion and rate-limiting.

</comment><comment><USER35> > In this post we'll have a look at some instances of such sitations, their > "ad hoc" solutions provided at the language level, and finally at how these > problems can be solved in a uniform way using Monads.

I wonder if the blog post's author is actually aware that the original application of monads to programming languages was _precisely_ to give a denotational semantics to strict higher-order languages. In other words, you don't "add monads" to JavaScript. A monad, perhaps an entire monad transformer stack, is already hardwired into its semantics.

Now, I'm aware that the author says at the end:

> We've had a look at this from a syntactic perspective.

But monads are about semantics, not syntax. Of course, if you want uniform syntax for using monads, then _say just that_.

\---

> For-loop Hell occurs when iteration through multiple dependent data sets is > needed. Just as for null-checking, our code becomes deeply nested, with a > lot of syntactic clutter and needless bookkeeping.

You know what's a simple, clean, straightforward solution to "for-loop hell"? Helper procedures. It baffles me why people always reach for the bazooka when a fly swatter will do.

> Both the State and ST monads bound the lifetime of a stateful computation, > ensuring that programs remain easily reasoned about in the general case.

Yet neither can express the following very useful pattern:

        allocate A
        allocate B; use A B; deallocate A
        allocate C; use B C; deallocate B
        ...
        allocate Z; use Y Z; deallocate Y
        deallocate Z

> The `ST` Monad provides more performant state with references, at the cost > of some higher order behaviour.

`ST` is not about "performance". It's about semantics. With `State`, you have to know beforehand the state type, and you cannot change it in the middle of the computation. With `ST`, you can allocate whatever you want in the middle of a computation, and it doesn't have to be reflected in the computation's type.

<comment><USER36> you can use monads to do your last example....

<comment><USER35> No, you need proper substructural types. Not even monadic regions will help.

<comment><USER36> You do not need a type system to use monads. In particular, your example could be written (in a statically typed Haskell-like language) using indexed monads. In a dynamically typed language, you wouldn't need that.

<comment><USER35> Of course, you don't need types to write programs. Types are just a way to mechanically verify some desirable properties. But, as it turns out, resource management in large programs is pretty damned hard to get right without this kind of mechanical assistance. So, of course, when I say "it's inexpressible without <type system feature>", what I mean is "it's impossible to mechanically verify it without <type system feature>".

<comment><USER36> Monads have nothing to do with verification, so I'm now unsure what your original point was.

It's not surprising that you can't use a banana to edit text, so it's not surprising you can't use the general idea of monad to do verification.

<comment><USER35> > Monads have nothing to do with verification, so I'm now unsure what your > original point was.

Indeed, monads are about language semantics, prior to any verification attempt. Have you tried actually tried reading my original comment?

<comment><USER36> Your original comment was about language semantics. You then provided an example of something you claimed could not be done monadically. I pointed out that you could implement such a thing with "indexed monads", which are a subclass of monads (although not one that's easily used in any current programming language, Haskell included).

You then claimed that in order to implement the memory allocation example you would need substructural types, which is not the case. Then you claimed that you needed the type system feature to verify the memory was allocated/released correctly.

You are correct that you need an advanced type system and type checker to do the memory validation. However, the validator tool only needs to know about one monad (your resource one). This one monad is a small subset in the very large space of 'things that form a monad'.

It's like if I said, 'groups are about arithmetic'. While true that many arithmetic operations can be expressed as a group, groups are not inherently about arithmetic. That would be conflating common use cases with the generalization.

<comment><USER35> > You then provided an example of something you claimed could not be done > monadically.

Using a _monad_ , i.e., an endofunctor with unit and join that satisfies the well-known laws, you cannot do it.

> I pointed out that you could implement such a thing with "indexed monads", > which are a subclass of monads (although not one that's easily used in any > current programming language, Haskell included).

Is a so-called "indexed monad" really a monad, now?

> You then claimed that in order to implement the memory allocation example > you would need substructural types, which is not the case.

It is the case. What else could be the point to the threaded typestate in the definition of so-called "indexed monads"? Moreover, even with the threaded typestate, so-called "indexed monads" may fail to achieve the desired goal of manipulating resources linearly, e.g. the "indexed list monad" provides no such guarantees.

</comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER23> What happens when you mix what <\- means :

do

      a <- getData // this is a awaiting a future

      b <- getMoreData a // this is looping a list

      c <- getMoreData2 b // this is null checking

      d <- getEvenMoreData a c // this is awaiting another future

      print d

Monads' hell, isn't it ?

<comment><USER37> Being able to combine monads like this is part of the point.

<comment><USER23> it means that the fact that the monad is looping or checking for null or awaiting a future is coded in the function itself, and hidden when reading the for loop. When types are heavily overloaded, it can take minutes to know if we are looping a iterable, awaiting a futurable or checking for null a maybeable. And what about a Maybe(List) ? a Future of list ? Common, how is this not Hell ?

<comment><USER38> Haskell's type inference is optional: if you felt the above code is difficult to understand, you could manually specify the type of each statement.

In a language with a less powerful type system, you could write the same information in comments, but then the compiler wouldn't warn you if you accidentally changed the side effects of a statement.

</comment></comment></comment></comment><comment><USER39> I think this is another instance of solving the wrong problem.

        var a = getData();
        if (a != null) {
          var b = getMoreData(a);
          if (b != null) {
            var c = getMoreData(b);
            if (c != null) {
              var d = getEvenMoreData(a, c)
              if (d != null) {
                print(d);
              }
            }
          }
        }

Why not simply

        var a = getData();
        if (a == null)
            return;

        var b = getMoreData(a);
        if (b == null)
            return;

        var c = getMoreData(b);
        if (c == null)
            return;

        var d = getEvenMoreData(a, c)
        if (d == null)
            return;

        print(d);

And the other example

        var a = getData();
        for (var a_i in a) {
          var b = getMoreData(a_i);
          for (var b_j in b) {
            var c = getMoreData(b_j);
            for (var c_k in c) {
              var d = getMoreData(c_k);
              for (var d_l in d) {
                print(d_l);
              }
            }
          }
        }

Yes, there is the issue that there is too much nesting. But there is no point in tackling this problem with a clever monad. That's not solving the issue, it's just hiding it. Operationally there is no difference.

What really needs to be done is to avoid data dependencies. It's typically possible to do something like

        for (var x in a)
            foo(x, a_state);
        for (var x in b)
            bar(x, a_state, b_state);
        for (var x in c)
            baz(x, a_state, b_state, c_state);
        for (var x in d)
            quux(x, a_state, b_state, c_state, d_state);

This not only looks cleaner, it _is_ cleaner. The path of execution is simpler. It will also often run much faster, since its only tight loops and uniform data accesses.

<comment><USER40> The example in the article opens itself to an attack like this because it's simple (in an attempt at explaining things simply). It's easy to mistake the trivialness for naivety.

But the "hell" part that monads solve really arise when you go further than this -- when you have error handling, null handling and asynchronicity and mutable state involved. For example, if each of these functions could return an Either or Maybe, your non-monadic, "if"-based version would get a lot hairier.

Monads abstract and generalize the concept of chaining computations. _Of course_ you can write the chaining manually, but you would have to replicate the same logic for every chain of function calls, with all the ad-hoc error handling and so on in place. It may look "cleaner" to you, but there's no generalization happening, and monads exist to generalize patterns like these into a single tool that can used over and over again.

This is why every single monad code example in the article is identical.

<comment><USER39> Yes, you can implement an "error monad" instance for each of a given set of procedures (returning Either, Maybe, or whatever).

You can also wrap each of a given set of procedures that don't conform to a uniform interface (say, return null or < 0 on error) to be conformant. That's just basic hygiene. I don't see a problem.

> Monads abstract and generalize the concept of chaining computations.

I get that, but in the real world I don't find any need beyond sequencing (first do this, then do that) and the occasional nested-for or early return. Everything else is only giving up on other things that are extremely important, like modularity (complex types / protocols are inherently anti- modular) and deterministic resource usage.

> This is why every single monad code example in the article is identical.

I didn't even notice that, and I do not consider this a desirable goal at all. The examples do totally different things, and you _want to see that_. There's no need to swap one out for the other in any realistic scenario. Ever.

<comment><USER16> > in the real world I don't find any need

And I'm sure you're pretty productive with your choice of language, but bear in mind that tools shape our thinking. You don't find yourself reaching for those tools in part because you've never expected them to be there. That doesn't mean they can't be very useful.

<comment><USER17> Exactly. That's why I would never write any of the ad-hoc examples the way they are written. And that's why the article is criticized.

</comment></comment></comment></comment></comment><comment><USER41> Definitely a really neat set of examples. As someone not familiar with Haskell, I have two questions though:

1) What would the method signatures look like in these examples? I.e on the list example, I'm assuming getData would be () -> list(A). And then is getMoreData (A) -> (B) [which gets lifted to list(A) -> list(B)]?

2) How would you combine multiple of these approaches at once? E.g. using both a state monad and a list monad? Would you have to use nested do blocks? Or would you typically define your own custom monad that is a combination of state and list, writing your own lift method, etc.?

<comment><USER42> 1) Maybe monad

      getData :: Maybe Data1
      getMoreData :: Data1 -> Maybe Data2

Note: the monad is probably not just Maybe if it talks to the outside world but more in 2)

List monad

      getData :: [Data1]
      getMoreData :: Data1 -> [Data2]

Dont' know about continuations.

2) There are a few approaches but the most popular are monad transformers, building stacks to combine the effects. For example, to speak with the outside world we need 'IO'. To add failure we might use the Maybe transformer

      MaybeT m a

to build

      type IOMaybe a = MaybeT IO a

<comment><USER19> For the list example: I don't get why that loops over the content of the list (I don't understand this in the OP either). Wouldn't it need to be:

      getMoreData :: [Data1] -> [Data2]

at least? As I understand the OP, wouldn't the function signature for the non- monadic example be:

      getMoreData :: Data1 -> [Data2]

and the function body fundamentally different for that reason?

</comment></comment></comment><comment><USER24> Am I the only one who found the "ad-hoc" solutions more clear?

I appreciate that they make it obvious to the reader which things are loops, which are null-checking, which are async, etc.

I'm sure the unified do-notation is very satisfying to write, but it seems confusing to read.

<comment><USER43> One of the few empirically findings of programmer productivity, is that programmers can produce about the same number of working lines of code per day regardless of the language. And the ratio of bugs / lines of code is relatively constant across languages.

So expressing the exact same behavior in fewer lines of code directly leads to higher productivity, and fewer bugs for equivalent functionality.

In other words, there is a concrete cost associated with overly verbose programming language constructs.

<comment><USER24> source?

If that's actually true, we should all be using CoffeeScript:

[http://redmonk.com/dberkholz/2013/03/25/programming- language...](http://redmonk.com/dberkholz/2013/03/25/programming-languages- ranked-by-expressiveness/)

According to that analysis, it's more expressive than Haskell, Scala or Clojure (all of which otherwise rate quite well).

Regardless, the "ad-hoc" solutions are all about the same LOC as the do- notation syntax, so I'm not sure the LOC argument is relevant here.

I would assert that bugginess and readability vary across coding styles, which is ultimately the question at hand, not language (ie; you can write comprehensions in Haskell too).

</comment></comment></comment><comment><USER44> Discussions like this are always helpful for people with more experience in dynamic languages. My first experiences with Monads, like the one in LYAHFGG[0], left me with the sense that Monads were a tool primarily used in statically-typed languages. After much searching, I stumbled across Tom Stuart's _Refactoring Ruby With Monads_[1] talk, which helped describe Monads as just another useful programming abstraction independent of the language. (Jim Duey's _Monads in Clojure_[2] also helped.) Monads now make sense to me as a general-purpose programming paradigm, like recursion or immutable data structures.

[0] [http://learnyouahaskell.com/a-fistful-of- monads](http://learnyouahaskell.com/a-fistful-of-monads) [1] [http://codon.com/refactoring-ruby-with-monads](http://codon.com/refactoring- ruby-with-monads) [2] [http://www.clojure.net/2012/02/02/Monads-in- Clojure/](http://www.clojure.net/2012/02/02/Monads-in-Clojure/)

<comment><USER45> not sure if you've seen this clojure lib [http://funcool.github.io/cats/latest/](http://funcool.github.io/cats/latest/)

</comment></comment><comment><USER46> The elegance of this solution IMO comes to this:

\- you mastered the art of reading math papers, love seeing f: XxYxZ -> D notations and enjoy (partially) composing functions in papers you write. You are on academic track for PhD or higher. It's your natural habitat; ideas are always more important than current mediocre reality; real-world is just a side effect. You are going to love monads. You'd treat monad transformer hell or other warts as necessary and unproblematic.

\- you went into programming by observing real-world, how each action modifies environment and how interactions affect each other. You saw a great analogy to those when you started with your first language such as Python/Basic/Java/Pascal/etc. Then you started to optimize runtime more and more and now can't write a line of code without addressing all kinds of performance and consistency issues. You are likely going to hate monads if you ever manage to understand them.

<comment><USER47> This is very black and white thinking. I started with imperative languages, loved them. Then I learnt some FP theory and Haskell, loved it. I now use both and what's most important imho is that knowing both made me a better dev overall.

</comment></comment><comment><USER48> This paper calls attention to my biggest source of discomfort with Haskell's approach to monads: They end up hiding so much under the covers that everything starts to look the same. The author leaned on this particularly hard for rhetorical effect in the article, but it's not always so different in the real world. It really harms readability. I've noticed, for example, that it's not unheard of for someone to come asking for help with a do-block's behavior, and the first response they get is someone having to ask what monad that do-block is using.

F#'s approach (which it calls computation expressions) makes a small tweak that makes all the difference in the world - instead of always using the word "do", you start a block with the name of the monad you want.

So instead of

      do { ... }
      do { ... }
      do { ... }

everywhere, you get:

      maybe { ... }
      seq { ... }
      async { ... }

<comment><USER33> Firstly, that's almost never a problem as you almost always have a type signature to hand.

Secondly, F#'s approach is not a small tweak. It's forced on them by a lack of higher-kinded types.

Thirdly, if it really bothers you use TypeApplications to write

        with @Maybe $ do { ... }
        with @[] $ do { ... }
        with @Cont $ do { ... }

<comment><USER16> I assume `with :: forall m a. m a -> m a; with = id` - is that defined somewhere?

<comment><USER33> No, I just made it up but if enough people shared the OP's feelings it _would_ be defined somewhere. The fact that it doesn't exist is evidence that it's not needed.

<comment><USER16> A fair point, but weakened somewhat by the fact that type applications are as new as they are.

</comment></comment></comment></comment></comment><comment><USER49> Clojure has some conditional threading macros like `some->` and `cond->` that are useful for transforming data conditionally.

`cond->` takes pairs of tests and forms where a form is threaded through the subsequent forms if the test expression is true.

Example from documentation ([https://clojuredocs.org/clojure.core/cond-%3E](https://clojuredocs.org/clojure.core/cond-%3E)):

      (cond-> 1          ; we start with 1
          true inc       ; the condition is true so (inc 1) => 2
          false (* 42)   ; the condition is false so the operation is skipped
          (= 2 2) (* 3)) ; (= 2 2) is true so (* 2 3) => 6
      ;;=> 6
      ;; notice that the threaded value gets used in
      ;; only the form  and not the test part of the clause.

<comment><USER50> This is conceptually different to a Monad in Haskell. Monad bind operations have short circuit failure, so in the example above all of the operations would have to succeed or none of them would.

cond-> looks like a useful function but you have to hold the state in your head at each point to debug it. What happens if two steps change the type from int to string then the follow step requires the string, but if the previous step fails you would get an int? Seems it would be very prone to runtime surprises

<comment><AUTHOR> _cond- >_ doesn't, but _some- >_ short circuits on _nil_. Similarly, _with_ expressions in Elixir short circuit on a failed pattern match.

[https://clojuredocs.org/clojure.core/some-%3E](https://clojuredocs.org/clojure.core/some-%3E)

[https://hexdocs.pm/elixir/Kernel.SpecialForms.html#with/1](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#with/1)

</comment></comment></comment><comment><USER51> My one gripe is the author doesn't exactly explain what the problem with those ad-hoc solutions are. I lied, I also have the gripe that the author doesn't talk about the noncomposition of monads and tease monad transformers.

</comment><comment><USER52> Deterministic finalization is another example, with "as hoc solutions" including manually using a finally statement, using an interface and a custom statements (such as the with statement from Python and the using statement in C#, or now the try-with-resources statement from recent Java), or syntax like stack allocation (as in C++). And of course error handling in general (not just null value checking), with exceptions being the typical "ad hoc solution". Any time you have pieces of code going together in some boiler- plate fashion, monads are pretty epic, and it is incredibly depressing to see people not really learning this lesson (such as in Rust, which went with all of crazy operators, macros everywhere, and "just do it manually as we don't believe in exceptions but also don't fully understand monads" as their "ad hoc solution" to error handling, when what the language really needs is do syntax to go along with its attempt to rely on the Either monad for all of its errors: monads are largely interesting because of do syntax, which is the payoff for the common abstraction).

<comment><USER53> Usually someone complains to me that GC FP languages lack deterministic finalization, I end up explaining how to use higher order functions to achieve it.

The problem with _with_ , _using_ or similar approaches is that they grew with the language and the majority of them don't allow for trailing closures.

More modern languages like Swift or Kotlin make it much nicer to achieve that, making something like _using_ a simple function call.

<comment><USER54> I don't get how higher order functions help with deterministic finalization in the case of closures, which typically have an unbounded lifetime. How, and when, is the resource captured by a closure disposed of?

<comment><USER53> When the closure itself is disposed of, depends on the GC algorithm (RC, tracing, parallel...).

My point is about other kinds of resources, namely files, database connections, IPC channels, sockets, native memory buffers, transactions and so forth.

The call stack of higher order functions can be used as an arena.

</comment></comment></comment></comment><comment><USER55> I am still pretty new learning haskell, and find this very helpful. Not necessarily agree whether monadic solution is prefered, but I like how it shows how general monad is: it's hard to grasp the generalization from only a couple of simple examples normally found in any haskell book. I hope there are more articles like this showing how these abstract concepts can be applied in somewhat unexpected places.

</comment><comment><USER56> How is this not just an architecture that insures the return values/struct/object is a 'context object' that can be passed as input, and the architecture is arranged for as many functions as possible to pass and receive these standardized parameter contexts. This is just function chaining, a la jQuery, right? Or where is this assessment not right?

<comment><USER47> It kind of is, but this architecture has mathematically sound properties and is built in the language so people don't have to reinvent it in an ad-hoc way all the time. Your context object would be a Functor, types are employed to ensure that functions work with these and chaining of such functions is possible via Monads.

</comment></comment><comment><USER57> How is error handling done if something goes wrong in one of the functions?

<comment><USER58> It depends. In Haskell, functions do not fail in traditional sense - they just return indication of failure. So the return type of function can be, for instance, Either type (as someone already noted) which basically lets you have proper value and error value, one or the other.

And Either is also a monad. Typically, you would derive your own monad by somehow combining the two monads (for instance using a monad transformer) that would have a behavior you want.

In ordinary languages, the error handling is done ad hoc, in each situation the semantics can subtly differ. You can do that too but then you have to explicitly handle the fact that functions return Either in the function body (this would be somewhat similar to checked exceptions). Or you can define your own monad that prescribes the correct semantics of interaction between the monads.

<comment><USER59> > In Haskell, functions do not fail in traditional sense - they just return > indication of failure.

That's too general a statement. Haskell functions certainly can fail in the traditional sense. As a trivial example, "head []" is a well-typed Haskell expression that will raise an exception when evaluated; if the exception is not caught (using a traditional exception handler), then it propagates to an error, and the program exits.

This article [1] about the many ways to handle errors in Haskell is a bit old, but as far as I know, all his points are still relevant. The conclusion (for me) is that if modern Haskell tends to use return-values on failure, it's due to convention (and good taste) among developers, and not due to a design constraint of the language.

[1] [http://www.randomhacks.net/2007/03/10/haskell-8-ways-to- repo...](http://www.randomhacks.net/2007/03/10/haskell-8-ways-to-report- errors/)

</comment></comment></comment><comment><USER60> I like the ad-hoc solutions. They correspond more closely to what your code is actually doing. I used to work on a Scala code base that heavily used a functional style with monads, custom operators, and elaborate type hierarchies.

At the micro level these things seemed great, they removed a lot of "boilerplate", but when you zoomed out and tried to figure out how larger parts of the application worked it quickly became overwhelming because these language features made understanding what the program was actually doing much harder.

</comment><comment><USER10> I love this blog, monoid morphisms was very eye-opening for me.

</comment><comment><USER61> Hmm, maybe I'm missing something, but I lost interest after seeing that pretty much all the 'ad hoc' solutions listed (similar non-monad based solutions is the idea I think) were nearly identical to the monadic solutions, except some syntactic differences. As someone who doesn't care that much about little syntax nuances, the motivation to look further here escapes me.

</comment><comment><USER46> It's more like escaping one hell to another one. Monads introduce brutal conceptual complexity and only few managed to master them, usually at the top of intelligence range in the math spectrum. It's unlikely this is going to be a solution for average or even many advanced developers that won't be able to comprehend it.

<comment><USER62> > usually at the top of intelligence range in the math spectrum

As someone who is definitely not at the top of the `math intelligence spectrum' but does have a reasonable understanding of monads (in a practical, not category theory sense), I can promise you that this isn't the case.

Yes, it takes a while to get your head around them - but this is mostly due to poor teaching materials. I wouldn't class them as significantly harder than many of the other concepts required to become a good programmer.

This isn't to say that monadic solutions are an answer to all problems - <USER2> they're interesting to learn about.

</comment></comment><comment><USER63> Here's a little secret: in Java, try + generic catch is my error handling monad.

<comment><USER64> They're not nearly as good as as an Either type, but if you don't have do notation, exceptions are much, _much_ , easier to use than sum types for error handling.

<comment><USER65> Yep. If you want to be really broad, even golong's (val, err) is a sum type even tho tuples are more literally product types. Since it's generally one or the other that has meaningful value, not both.

But it sure as hell isn't easy since there is no do syntax or flatMap/selectMany/whatever to handle them nicely.

</comment></comment></comment><comment><USER66> This article is more religious than technical. You're meant to be inspired by the elegance of it all, not necessarily to understand much about the use of monads in practice.

</comment><comment><USER67> So the monad style hides completely what is going on. That all the solutions look exactly the same impairs readability of the code.

<comment><USER68> Isn't that the point of encapsulation?

</comment></comment><comment><USER69> > Monads can help solve certain classes of problems in a uniform way.

You solve 3 completely different problems using the exactly same code and have the gall to call this less complicated? I'm forced to sometimes wonder whether functional programmers have any idea how to create software.

If this was a joke I didn't understand, I apologise for my thickness.

<comment><USER70> It's called abstracting. The problems fit the Monad interface. Details are in the implementations.</comment></comment>


Paychecks at the top tech companies - Facebook pays more than anyone on average - <AUTHOR> http://www.cnbc.com/id/40129303

<comment><USER2> I love this comment under the post: _Software engineers? You mean programming Python? Python is as easy as adding 1 + 1. Something else is going on, illegally, inside Silicon Valley._

oh no you didn't.

</comment><comment> space-monkey Show me the median.</comment>


A C Compiler for Stack Machines (2006) [pdf] - <AUTHOR> http://www.dcs.gla.ac.uk/~marks/thesis.pdf

<comment><USER2> From the thesis abstract:

> _" Included with this thesis is a portable C compiler for stack machines, > which incorporates these new register allocation methods. The C compiler and > associated tools (assembler, linker and simulator) are included in the CD."_

I looked at Mark Shannon's page below but didn't find a link to an ISO image of the mentioned CD.

[http://www.dcs.gla.ac.uk/~marks/](http://www.dcs.gla.ac.uk/~marks/)

As far as I can tell from a quick (and very casual) skimming, Mark's lcc-s is implemented as a backend for lcc.

[http://www.cs.princeton.edu/software/lcc/](http://www.cs.princeton.edu/software/lcc/)

[https://sites.google.com/site/lccretargetablecompiler/](https://sites.google.com/site/lccretargetablecompiler/)

[https://github.com/drh/lcc/tree/master](https://github.com/drh/lcc/tree/master)

If anyone has found the mentioned lcc-s code, please post a link.

<comment> david-given I've actually been thinking about this recently (in order to compile C into small, dense code for running, slowly, on 8-bit microprocessors). I'd really like to see this as well.

</comment></comment><comment><USER3> What timing - I just read "Stack Computers: the new wave" by Philip Koopman ([http://users.ece.cmu.edu/~koopman/stack_computers/contents.h...](http://users.ece.cmu.edu/~koopman/stack_computers/contents.html)). I'm pretty sure it was recommended by someone on HN, but it's quite a nice mid\late 1980s take on a tech which never really took off. I wonder what Koopman would have thought about how things turned out.

<comment><USER4> > never really took off

It, literally, took off pretty far and at a very high velocity: [https://en.wikipedia.org/wiki/RTX2010](https://en.wikipedia.org/wiki/RTX2010)

<comment><USER3> Wow that's really cool! This is something I'm extremely happy to have been corrected on, thanks!

</comment></comment></comment><comment><USER5> What is missed here is space optimization like what human do in Forth.

Zero-operand instructions tend to have the same layout for same semantics. This contrasts them with three-operand or even one operand instructions sets, where adding two values can have several encodings. add r1,r2,r2 (for r1 := r2+r3) is different in encoding than add r2,r3,r4. The precise indices of registers depend on the surrounding - how they are allocated elsewhere. Thus the probability that two semantically identical instruction sequences would have same encoding quickly goes to zero as instruction sequence increase. x[i] = y[j] can have 31^4 encodings for MIPS as upper bound even without considering instruction order.

For stack-based zero-address instructions you will have ADD wherever you need to add two values. x[i] = y[i] will have same encoding up to reordering (compute x[i] address first or second). The number of reorderings is finite and here we come to the salient part: we can abstract away operations like compute address of x[i] into their own definitions. We will have one call for, say, three instructions and RET.

This call is also a target for reductions. Instead of long sequence of stack operations we can now have two calls to COMPUTE_X_I and something like ROT between them. Are there sequences like this somewhere? Of course there will be. Repeat till the fixed point. It is pretty much like LZ78 algorithm - encode string into it's own symbol.

The closest thing to this I saw was a paper about compiler for VLIW DSP that generated stack code for most of program and VLIW code for the performance critical parts. They created opcodes for most frequently used opcode sequences, but that's all. They still demonstrated significant code size reduction, but nowhere close to Forth-style compressed code that produced by Forth programmers.

</comment><comment><USER4> An interesting topic, did not know there is such a comprehensive work on it. My initial (lazy) take was to reconstruct expression trees out of an SSA, reordering where appropriate (with no side effect order changes). I only did "register allocation" for the remaining stack-allocated slots then.</comment>


Scanning Alexa's Top 1M for AXFR - <AUTHOR> https://en.internetwache.org/scanning-alexas-top-1m-for-axfr-29-03-2015/

<comment><USER2> They don't actually explain how to disable AXFR...saying just: "The easiest way to fix this issue is to re-check your dns server's configuration file. Make sure that the nameservers only allow AXFR to subsidiary nameservers and that these aren't allowed to answer AXFR requests."

In BIND, this is configured by the allow-transfer option. You can explicitly allow your slaves with an option like:

        allow-transfer { 192.168.1.1; };

Or, disable all transfers by specifying "none;". This can be done on a per- zone basis, as well, though the global section will apply in the absence of zone-specific configuration, which I suspect is how so many servers are misconfigured (i.e. there is no rule in place to block it in the global section, so it is allowing all for zones that don't have an allow-transfer section). I just noticed that some of my zones on slave servers fall prey to this, as well, even though I know better. The default seems to be to allow all, if allow-query allows all.

That said, I'm not overly alarmed. Very little (roughly zero) sensitive data exists in my world-facing zones.

<comment><AUTHOR> Hi, thanks for the feedback!

We thought about putting some "example fixes/configurations" into the blogpost, but then abandoned the idea, because there are a lot of different DNS servers out there.

Only covering a few didn't seem useful to us.

So thank you for giving an example configuration for BIND :)

<comment><USER2> Haha...you know enough to know that BIND has tremendous market share. It _may_ not be the best name server, but it's _definitely_ the most popular. Why not help 65%+ of name server administrators with specific advice?

<comment><AUTHOR> Yeah, you're right. We've updated the blogpost.

Thanks!

</comment></comment></comment></comment><comment><USER3> The article author seems to ignore the existence of views. If you have confidential data query-able from the outside, it's a much bigger issue than wide open AXFR... Restricting AXFR is more cute than efficient, the information still leave your network unencrypted.

[http://www.cyberciti.biz/faq/linux-unix-bind9-named- configur...](http://www.cyberciti.biz/faq/linux-unix-bind9-named-configure- views/)

<comment><AUTHOR> Hi,

that's another good point!

Thanks for bringing it up.</comment></comment>


Outright was just acquired by Godaddy - <AUTHOR>

Dear Outright Customer,
Today, Outright opens a new chapter in our company's history. I want to personally share it with all of you, our loyal customers. Outright has been acquired by Go Daddy, the world's largest web hosting provider.* Outright is now a Go Daddy company.
I know the first question that comes to mind is "What does it mean to me as an Outright customer?" I want to be very clear about this.
Your Outright service will remain the same. Continue using it as you do today. In the future, you may have access to more services and help, such as additional customer support options. The Outright team is excited to join the Go Daddy family and its more than 10 million customers, the majority being small business owners. We are combining forces with a company that has built a billion dollar business with the simple idea of providing great products and award-winning customer service. Outright and Go Daddy are both 100% committed to providing easy-to-use, affordable solutions to help you run and grow your business.
Like I did, many of you probably recognize Go Daddy for its controversial Super Bowl commercials. Go Daddy is much more than a company with edgy ads, it is a company committed to customer service and helping small businesses grow online. And, by the way, Go Daddy's advertising is shifting, as you'll see in the upcoming Olympics. The commercials are evolving to focus more on what the company does to help its customers.
Helping customers is what we're all about and we are excited to join this journey and continue to bring services to small businesses like you.
Please be assured that our privacy policy is not changing at this time. We will provide you with notice and an opportunity to opt-out in the event of future changes.
I know change can be challenging. If you have any questions about this, please don't hesitate to reach out to me directly at email@example.com or contact our friendly support team at firstname.lastname@example.com.
Sincerely,
Steven Aldrich,
CEO of Outright <comment><USER2> Does anyone have suggestions for an alternative to Outright? I recently signed up with them and was really pretty happy with the service but GoDaddy has earned a permanent spot on my no-fly list and there's no way I want them to have access to my financials or my banking data.</comment>


Good book for understanding the current economic crisis? - <AUTHOR>

I imagine many HN readers wish they knew more about how we got into this economic mess. If you've read a (recently released) book about the cause of the economic crisis, please share the title and why you recommend it! Thanks <comment><USER2> Meltdown by Thomas Woods:

<http://www.amazon.com/exec/obidos/ASIN/1596985879/>

It clearly and accurately explains the real causes of the "crisis" (hint: it's not unbridled capitalism).

<comment><USER3> Absolutely the best by far. I know you said no older books, but this one gets it down to basics, and always seems to be an example of "Those who fail to learn from history are doomed to repeat it," is

Henry Hazlitt's Economics In One Lesson [http://www.amazon.com/Economics-One- Lesson-Shortest-Understa...](http://www.amazon.com/Economics-One-Lesson- Shortest- Understand/dp/0517548232/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1237881084&sr=8-1)

<comment><USER4> Free articles are available at mises.org, there are enough articles to keep you reading for months/years. Several of the authors predicted the housing bubble bust before it happened although they did not provide an exact time. You won't always agree with the articles but they will make you think.

Recent articles cover the issues and effects with the current administration's budget and economic plan along with more fundamental economic issues.

There is also a section with free books if you do not mind reading on the computer. There is also at least one guide to readings on the mises.org site.

Both of the books mentioned in previous posts are available through the mises.org bookstore.

Also check out Robert Murphy's "The Politically Incorrect Guide to Capitalism" as another primer on economics.

</comment></comment></comment><comment><USER5> From the left side things: Robert Brenner's Boom and The Bubble

[http://www.amazon.com/Boom-Bubble-US-World- Economy/dp/185984...](http://www.amazon.com/Boom-Bubble-US-World- Economy/dp/185984636X)

</comment><comment><USER6> <http://crisisofcredit.com/>

Not a book, but a very nicely done animated introduction to the crisis.</comment>


Don't Hijack Browser Keyboard Shortcuts - <AUTHOR> http://hypertexthero.com/logbook/2014/04/dont-hijack-browsers-keyboard-shortcuts/ <comment><USER2> Blogger is notorious for "reimplementing the web experience". Just try opening a Blogger page on an iOS device. You'll get an empty page, then spinning gears, then after a while the page will finally land. Then you'll have a page which won't scroll properly. Because someone just _had_ to reimplement scrolling. Better.

Let's take the horrible Onswipe themes as another example. They not only break functionality and make the page slower, but also break zooming in and show buttons that _pretend_ to be iOS buttons, but aren't.

I could rant about this for hours. It's all the same basic problem: people trying to redefine/hijack basic browsing functionality. I interpret this as extreme hubris ("I know how to design this better!") or arrogance (" _this_ is how you will view my site, period!").

<comment><USER3> Urban Dictionary's scrolling was for a while completely and totally broken on my Android phone. I couldn't scroll at all.

</comment></comment><comment><USER4> The advice of this article is good, but I don't think it should be up to individual website authors to behave well. Ideally, there ought to be a standardized javascript API for binding control keys. Then the browser could prohibit rebinding if desired (while giving feedback to the webapp as to whether rebinding was allowed), and provide an accompanying UI for the user to see which controls are enabled/disabled, to whitelist or blacklist websites, and so on.

<comment><USER5> Yes please. Especially if it has a single browser option to disable all key rebinding.

</comment></comment><comment><USER6> One of the dumbest I've run into is to jack ctrl-f and send it to a site search box. If I use ctrl-f, it's because I meant to do an entirely different thing, or by accident. In no case is it because I want to search your article archives.

<comment><USER7> Likewise slash. I appreciate the nod to vim, but Firefox is already nodding there.

<comment><USER6> If by nodding, you mean nodding out. For some reason, they've specially crippled the '/' search, and removed the configuration variable to make it identical to ctrl-f (next/last arrows mostly.)

If you happen to read this and are irritated by the same thing: I was saved by "Findbar Tweak." New essential plugin for me.

<comment><USER7> I've no objection to configurability, but I don't _want_ slash to behave the same as ctrl-f. In particular, when my /-search matches part of a link, hitting return follows the link. Ctrl-f searches for next, which functionality I already have access to with ctrl-g.

Edited to add - how can you stand the lack of next/last arrows in vim?

</comment></comment></comment></comment><comment><USER8> Far worse are websites like Battle.net that hijack the onpaste events to prevent pasting passwords. Hijacking keyboard shortcuts may cause inconveniences but prohibiting password pasting is a security flaw.

<comment><USER9> Do tell, how is that a "security flaw"?

<comment><USER10> It could be that some people use password managers that require pasting. (though many don't) It could lead to people using passwords that are easier to remember if their password manager doesn't work.

<comment><USER9> I guess that _is_ something of a double-edged sword then. You might force someone to use a weaker password, but then hopefully they wouldn't be keeping it in a place where they could simply copy/paste it. This really starts to delve into the whole "security is a gradient with tradeoffs" situation.

<comment><USER3> >hopefully they wouldn't be keeping it in a place where they could simply copy/paste it.

???

Passwords can be simple copy/pasted from.

Encrypted files can be simply copy/pasted from.

<comment><USER9> I'm assuming in this scenario that they would be keeping passwords in a plaintext file. If they kept passwords in an encrypted file, wouldn't they need to decrypt it? Wouldn't you presumably have a strong password to decrypt it? Where is that kept? How strong must one's password be when that password is keeping _other_ passwords secure? If they can remember that password, why can they not remember others?

<comment><USER11> Remembering 1 password is easier than remembering dozens of them. Reusing passwords is not a great idea, so dozens of passwords is a real concern.

It's also the case that disabling paste doesn't do anything to stop a user from storing their passwords in an unencrypted file.

</comment></comment></comment></comment></comment></comment></comment><comment><USER12> Yahoo Mail hijacked the down arrow: Looking in the preview pain, press down arrow to scroll... and you jump to a new mail. Very, very jarring and frustrating. I recall they also hijacked a bunch of other keys, none of which made much sense, which is sad... mostly because it shows that they don't use their own products enough to see how this can affect users.

<comment><USER13> Google+ appears to do the same thing with C-PgUp and C-PgDown; if I had wanted those keys to stop working properly, I would have used some ass-backwards browser like IE. If I've got a Google+ post open and I'm scrolling brisking through tabs, it's like hitting a brick wall.

</comment></comment><comment><USER14> Well, I don't think it's a bad idea to have specific shortcuts which disable the normal behaviour of a browser, and improve the UX of a website. If they exists:

* they should be explicitly enabled (i.e. RES for reddit)

* you should be notified if they are changing browser behaviour, and an option to disable shall be provided.

<comment><USER3> In practice the only way users are going to discover these "features" is by accident. How would someone be notified the behaviour is changing? The About page nobody reads?

<comment><USER14> Visual feedback when user executes a short cut.

</comment></comment></comment><comment><USER15> My personal pet peeve is the hijacking of / for in page search...

</comment><comment><USER16> The problem is not that sites are choosing to override browser shortcuts, but that they can do so at all. The browser should not allow its shortcuts to be overridden. In Vimperator you have to enter a pass-through mode, so this kind of overlap never happens.

<comment><USER17> I agree. But unfortunately many of the browser creators want to support full- fledged apps within a browser, which in their minds necessitates the rebinding of core shortcuts. A great example is command/control-s in Google Drive Documents.

Conflicting interests.

<comment><USER7> That's not a conflict, if you're using vimperator. In one mode, you pass whatever. In the other, you pass nothing. The only conflict would be around a site wanting to bind escape...

</comment></comment></comment><comment><USER13> _I'm talking to you, Blogger._

Is this the same Blogger that _requires_ JavaScript to view plain text? Or maybe I'm getting it confused with blogspot, I can never keep them all straight. In any case, I don't think it's a coincidence . . .

</comment><comment><USER7> This speaks to a broader issue with trying to keep every hotkey at the top level when you have multiple, nested containers. There is a fantastic solution to this: have a leader key that says "I am talking to my browser", where one of the sub-commands is "pass a literal leader key through". This is the way screen/tmux and ratpoison handle key bindings, and it means there is literally zero chance of a collision that I can't trivially resolve by slightly modifying my interaction.

</comment><comment><USER18> it sure is annoying, and let's not mention blogger's hyper-dependencies on javascript in order to display the page. No javascript, no content

anyway, well what can be done is \- prompt for user agreement to allow these shortcuts, then save it as user preference / cookie / etc..

</comment><comment><USER19> Ever tried the "Metro" version of Outlook Web Access, the one used with Office 365? It hijacks "Ctrl/Command + R" as a shortcut to "Reply". How oblivious is this?

</comment><comment><USER20> This is just the result of transitioning HTML to an applications framework. Now the application you use to view articles is not your browser, but Blogger (or WP etc).

</comment><comment><USER21> Yeah this is big to me. Even for system utilities. I use an OS X volume booster called "Boom"([http://www.globaldelight.com/boom/](http://www.globaldelight.com/boom/)) (which is nonfree but worth the $7) and it, by default, hijacks cmd + +/\- for zooming in chrome. Please don't do this!

</comment><comment><USER22> I have noticed issues with Firefox shortcuts while on YouTube, and have wondered if this sort of skulduggery was going on.

</comment><comment><USER23> Big examples would be PgUp and PgDn in Google+, and (at least on the old design), F5 on Twitter.

<comment><USER24> Google itself hijacks / (forward slash) which I use in Firefox for quick search. Super annoying.

</comment></comment><comment><USER25> I'm talking to you, Stackoverflow. I use Ctrl-k, Ctrl-b quite often.

</comment><comment><USER26> but what about things like ctrl-s and ctrl-b in Google Docs? Those are handy and I rarely save a page or create a bookmark by hotkey.

<comment><USER27> This is an inherent problem with web apps, since they're an app within an app. There are two different contexts fighting each other. Who's to say that Ctrl+S should save the app state or the page? Whatever we choose as the default, the non-default scenario would feel awkward when we need it.

I can think of two ways to solve this: (1) decouple apps from the browser frame or (2) use a special modifier key for app shortcuts (perhaps re-use the Windows key, e.g. Win+Ctrl+S).

<comment><USER28> (2) That was attempted (sort of)[1] and it failed pretty badly due to poor browser support and lack of understanding amongst users.

[1] [http://en.wikipedia.org/wiki/Access_key](http://en.wikipedia.org/wiki/Access_key)

<comment><USER27> Yeah, that's pretty messy. As an Opera user I had no idea that other browsers used Ctrl or Alt for access keys. That's just a recipe for disaster. Opera's Shift+Esc combo guaranteed no clashes with browser shortcuts, but it was really kludgy to use.

</comment></comment></comment></comment><comment><USER29> NoScript with whitelist works well enough.

</comment><comment><USER5> So fucking true. Obnoxious javascript masturbation pattern #47,601 that will make me blacklist scripts from your site. Same for single-key shortcuts (I'm looking at you there, JIRA...).</comment>


Agrivoltaics provide mutual benefits across the food–energy–water nexus - <AUTHOR> https://www.nature.com/articles/s41893-019-0364-5 <comment><AUTHOR> Coverage of this on ArsTechnica: [https://arstechnica.com/science/2019/09/crops-under-solar- pa...](https://arstechnica.com/science/2019/09/crops-under-solar-panels-can- be-a-win-win/)</comment>


Exposing Houdini's Tricks of Magic (1929) - <AUTHOR> http://blog.modernmechanix.com/exposing-houdinis-tricks-of-magic/ <comment><USER3> I was once enlisted to help with an illusion a vegas magician was working on.

Everyone I talked to about it (without knowing about my role) would take a minute to think about the problem, propose a solution, and be satisfied that they had discovered the method used. In reality that method was discarded because of a dozen or so complications that made it unworkable that nobody would have thought of.

I would highly recommend that anyone interested watch the Penn and Teller british series "Fool Us." The show basically centers around magicians trying to fool seasoned professionals with new and novel methods.

<comment><USER4> I have seen the Penn and Teller series and I would say it doesn't really offer that much in teaching about illusions because the ones that they bust are usually pretty obvious and if they aren't P&T will just say they know how it was done and won't give it away.

The tricks street magicians are performing these days are what amaze me. Dynamo has some stunts that are mind bending. Even watching it on video in slow-motion its magic. I love how unintuitive magic seems, but I suppose there must be a logical explanation to everything.

This is a good video that breaks down an easier trick Dynamo and I am sure other magicians perform:

[http://www.youtube.com/watch?v=UhYHB_XLuRo](http://www.youtube.com/watch?v=UhYHB_XLuRo)

<comment><USER5> That was interesting - not so much the trick itself, but the number of times I had to watch it before I finally got it. In the end, it seems so obvious - <USER2> human perception can be fooled easily it seems, so we're back on topic. Nice reference!

</comment></comment></comment><comment><USER6> The next parts:

[http://blog.modernmechanix.com/houdinis-mystifying-magic- stu...](http://blog.modernmechanix.com/houdinis-mystifying-magic-stunts- exposed/)

[http://blog.modernmechanix.com/houdinis-master-magic- tricks-...](http://blog.modernmechanix.com/houdinis-master-magic-tricks- explained/)

</comment><comment><USER7> I love the linked article on "Magic Tricks For The Amateur Chemist (1936)." Nearly every trick there involves adding sulphuric or hydrochloric acid to stuff :-)

</comment><comment><USER8> So how did he managed to get an elephant to disappear on stage? Or how he nearly joined Rasputin?

<comment><USER9> Yeah, I was a bit gutted to get to the end, and find a bloody cliffhanger!!!!! I'd love to read part 2.

<comment><AUTHOR> Part 2: [http://blog.modernmechanix.com/houdinis-mystifying-magic- stu...](http://blog.modernmechanix.com/houdinis-mystifying-magic-stunts- exposed/)

Part 3: [http://blog.modernmechanix.com/houdinis-master-magic- tricks-...](http://blog.modernmechanix.com/houdinis-master-magic-tricks- explained/)

Their site search is actually pretty good.

<comment><USER9> Ah, thank you.</comment></comment></comment></comment>


Hack initcwnd for faster page loading - <AUTHOR> http://www.cdnplanet.com/blog/tune-tcp-initcwnd-for-optimum-performance/

<comment><USER2> Great writeup. Have been hacking initcwd to way back when it was just hardcoded in the kernel. Other parameters not mentioned that control congestion:

1\. net.ipv4.tcp_slow_start_after_idle By default this is set to 1, which means, in a longer keep-alive connection, your connection will revert back to slow start (whatever you ended up setting it as per article) after "idle" (idle is 2 seconds last time i checked). Of course in a keep-alive connection you may have opened up your window from slow start to max, and you probably dont want it do default back to initcwd on subsequent requests. Especially applies on static file/cdn type servers where you probably are running longer keep-alives. You can just set this in sysctl.

2\. the last time i checked (years ago) if you run conntrack and turn off tcp_no_metrics_save, you get the benefit of the window opening up to the last remembered window size from your previous connection.

The concepts on increasing initcwd are particularly advantageous in the mobile arena where the rtt is usually much higher.

<comment><AUTHOR> I am somewhat skeptical about the benefits to mobile. the RTT is higher, so lower round-trips is good, but isint the risk of congestion higher in mobile? Say someone with a poor signal?

<comment><USER3> Good direction, but bad conclusion: "poor signal" is not the same thing as "congestion". This fact is what causes TCP over any form of wireless (including high-speed WiFi) to have been a really bad decision (and one that academic researchers the world over love trying to solve ;P).

The reason is that TCP makes an assumption (almost entirely true in the case of physical cable) that "packet loss" is always caused by "congestion" (due to the router simply throwing away packets it cannot handle), and so if you are losing packets you need to slow down your rate of sending, to help more of them get through.

However, if the reason you are losing packets is "poor signal", then you are going to get a pretty much constant rate of packet loss: if 10% of your airwaves are "damaged", 10% of your packets are going to be lost whether you are sending them at 100k/s or 1b/s (as your choice of "when to send" is entirely random from the perspective of the interference: your device is not modeling the underlying issue so it can try to "dodge the raindrops"; people work on this, though ;P).

The result is that when your signal is bad, even if you are currently getting 90k/s out after 10% loss, your standard TCP stack goes "oh shit" and starts dialing down its transmit window to "virtually nothing", leaving you unable to use that connection to get any data through anymore; even just opening a new connection when this happens (which may require restarting the app) tends to help tremendously.

(The solutions, for the record, all involve some sort of mechanism that allows explicit bookkeeping of either packet loss or congestion. However, this explicit bookkeeping requires various players that are not the device to be "in on it", and therefore makes it really hard to find the right balance of "who needs to install better routers to solve the problem", given the wide deployment of existing TCP... I mean, even getting IPv6 out there has been a tough sell, replacing IP entirely is a pipe-dream right now.)

</comment></comment></comment><comment><USER4> This is really interesting, but it seems like its the same information floating around on different blogs. If I didnt know better I'd assume they copy each other regarding this.

All lack some real and more thorough testing, they include that simple example, perhaps its enough, but its a bit light on the facts to get me to try it.

Would be interesting to know how this works in virtual environments, can I set this inside a VPS, or would the main kernel in the dom0(xen-host-stuff) override this?

Are there any sideeffects?

<comment><AUTHOR> id be posting some stats soon about the RWIN of traffic to our site. i.e. what % of users have a high enough RWIN to benefit from it. The setting works as expected on EC2 instances, i don't see why this would not work on dom0 as well. It doesn't need a kernel recompile, its just settings for your networking stack.

</comment></comment><comment><USER5> What I'm wondering is if that could have some influence on other protocols, too, like NFS. I'm going to do some testing.

<comment><AUTHOR> I think NFS usually uses UDP by default. Even when using TCP, I think increasing the initcwnd/initrwnd will only benefit the first few transfers after mounting. Would be curious to what you find out.

<comment><USER5> I did some initial TCP tests running netperf on a single GigE line, and there are some tenuous gains. I'll do NFS over TCP tests with 10 GigE or IB soon to get some meaningful numbers.

</comment></comment></comment><comment><USER6> We went through this last week on HN but this article is far more detailed. Thanks.</comment>


How we moved from Heroku to AWS using Docker - <AUTHOR> https://blog.progressly.com/how-we-migrated-from-heroku-to-amazon-web-services-aws-using-docker-38bef0b9d424#.3trjgmsnv <comment><USER2> Love the simplicity of the setup</comment>


'To Particularize the Alone Distinction of Merit': Blake's Visionary Imagination - <AUTHOR> https://www.nybooks.com/daily/2019/10/19/to-particularize-is-the-alone-distinction-of-merit-blakes-visionary-imagination/ <comment><USER2> > "The man who never in his mind and thoughts travel'd to heaven is no > artist."

The man who judges how others think thinks the least of his own shortcomings.

Also, he's dead.

<comment><USER3> Blake responds:

"To generalize is to be an idiot."</comment></comment>


World Domination, or At Least a Couple of Bucks - <AUTHOR> http://blog.wired.com/business/2008/04/world-dominatio.html <comment><USER2> Decent job of compacting the 9 hours into a few paragraphs.</comment>


Apple Patents Portrait-Landscape Flipping: the patent system is broken - <AUTHOR> http://gettys.wordpress.com/2011/07/18/apple-patents-portrait-landscape-flipping-the-patent-system-is-broken/

<comment><USER2> Everything in this article is false. The author admits having not even read the patent. This is just misrepresentation to further an agenda that wants to pretend that Apple didn't invent anything with the iPhone.

Reality: That compaq used a stylus, it was not a touch screen. And the patent doesn't say what is being alleged anyway... but then, its easy to construct arguments when you get to make up your oppositions position, right?

By definition, this whole thing is knocking down a strawman.

FWIW, every time I research one of these "alarming" "absurd" patents on an "idea", the turth turns out to be something else.

I'm convinced that the target audience never reads the patents or isn't conversant in the art sufficiently to comprehend them.

And thus these are essentially political posts to foster the idea that Apple doesn't deserve any protection for their inventions in the iPhone, because those making the claim are android fans or apple haters.

Reality is this: Prior to the iPhone, android was ripping off the blackberry. If Apple hadn't done this work, you'd still be arguing over which phone had the best physical keyboard and bespoke facebook interface.

<comment><USER3> 1\. The author has a valid reason for not reading the patent: there is an enormous disincentive to reading patents built into patent law (treble damages). Even if it was possible to glean useful information from the vague gobbldeygook that is a modern software patent application, reading them would still be a risky proposition.

2\. The "prior art" in this article isn't valid, but that doesn't make this patent good. Patents like this are bad for the industry.

Imagine if the WIMP interface had been patented out the wazoo like this back when Microsoft and Apple were duking it out for the PC market the first time (or even better, when Apple copied it from Xerox). Would that have resulted in a better outcome for consumers? For the industry? For _anyone_ other than patent lawyers? Absolutely, positively not.

Nobody invents in a vacuum; everyone builds on each other in a process of iterative improvement (even Apple; for the most recent example check out the blatant copy of Android's notification tray in iOS 5). If we all had to pay royalties to the entire stack of inventors who came before us, innovation would grind to a halt.

<comment><USER4> You're repeating a long disproved fallacy - Apple didn't steal from Xerox, they actually licensed the tech and then hired some of the key people like Alan Kay. Microsoft saw the same tech but didn't license any of it. They kind of went the same route they did when they created Ariel (an Helvetic clone). Apple licensed the font rather than just ripping it off.

<comment><USER3> I didn't say they _stole_ it, I said they _copied_ it. Despite what the content industry would like you to think, the words are not synonymous. Copying is not a crime.

Furthermore, Apple's license wasn't a patent license. It also didn't cover all of the things they copied. Xerox later sued Apple for copying (and, thankfully, lost, as did Apple when they sued Microsoft, because they tried to use copyright law instead of patent law).

</comment></comment></comment></comment><comment><USER5> This tragically recurrent idea that you can make up your own idea about what a patent covers without reading it is _absolute fucking horseshit_ and should be abhorrent to anybody that values truth over ideology.

No, Apple did not patent potrait-landscape flipping. It took me _about two minutes_ to verify this by reading the _actual_ description on the _actual_ patent.

[http://patft.uspto.gov/netacgi/nph- Parser?Sect1=PTO1&Sec...](http://patft.uspto.gov/netacgi/nph- Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL&p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7,978,176.PN.&OS=PN/7,978,176&RS=PN/7,978,176)

You don't even have to understand exactly what _is_ claimed to see that orientation-flipping itself _isn't_ being claimed. Just look at the background section:

 _Some portable devices use one or more accelerometers to automatically adjust the orientation of the information on the screen. In these devices, information is displayed on the display in a portrait view or a landscape view based on an analysis of data received from the one or more accelerometers._

Again, this is background information leading up to the actual summary of the claims. This is what Apple patented a specific enhancement to. They did not patent mousetraps. They patented what they think is a better mousetrap.

</comment><comment><USER6> From Apple's patent filing:

 _Some portable devices use one or more accelerometers to automatically adjust the orientation of the information on the screen. In these devices, information is displayed on the display in a portrait view or a landscape view based on an analysis of data received from the one or more accelerometers. For these devices, the user may occasionally want to override the orientation displayed based on the accelerometer data. At present, such devices contain little, no, or confusing heuristics for ending the user override of the orientation displayed based on the accelerometer data.

Accordingly, there is a need for portable multifunction devices with more transparent and intuitive portrait-landscape rotation heuristics. Such interfaces increase the effectiveness, efficiency and user satisfaction with portable multifunction devices._

Sounds like Apple is fully admitting they were not the first to do this but their way of doing it is unique and better. It's more like they are patenting the user interface changing depending on orientation than the act of switching orientation itself?

</comment><comment><USER7> I don't want to defend the patent system, but, I thought this patent was a page flipping lock gesture, not page flipping itself.

<comment><USER8> Does it really make a difference to the quality of the patent?

<comment><USER7> It makes a huge difference to the case against it.</comment></comment></comment>


Your Coding Philosophies Are Irrelevant - <AUTHOR> http://prog21.dadgum.com/142.html

<comment><USER2> Sometimes you just have to do what pays the bills. I can't tell you how many broken PHP apps I've worked on over the years.</comment>