17 ms·
Monads are monoids in the category of endofunctors
- slumpt_ 5y agoraises the question* Begs the question has a specific meaning. https://en.m.wikipedia.org/wiki/Begging_the_question https://en.m.wikipedia.org/wiki/Begging_the_question
- icedchai 5y agoLanguage changes over time: https://www.merriam-webster.com/words-at-play/beg-the-question https://www.merriam-webster.com/words-at-play/beg-the-questi...
- slumpt_ 5y agoYes, I’m aware that nonsense can be introduced into our lexicon by a sufficiently large population of people misusing meaningful phrases.
- CognitiveLens 5y agoLanguage evolves, as the wiki article you linked describes. Your prescriptivist nit-picking doesn't contribute to the discussion. From the HN guidelines: - Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. Assume good faith. - Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something. - Eschew flamebait. Avoid unrelated controversies and generic tangents.
- deleted 5y ago[deleted]
- Tade0 5y agoFunctional programming is subject to an enormous amount of gatekeeping. Kudos to the author for pushing that gate wide open.
- cool_dude85 5y agoAgree. Too often descriptions of monads assume that the reader has no formal math training whatsoever and do a lot of handwaving, diagrams, examples, etc. without actually providing a useful definition. This post is the exact opposite.
- the_only_law 5y agoThe closest I’ve come to understanding monads is the Wikipedia page on them (in the functional programming context, there’s also a separate monad page in the context of category theory specifically which is a lot more jargon heavy) https://en.m.wikipedia.org/wiki/Monad_(functional_programming) https://en.m.wikipedia.org/wiki/Monad_(functional_programmin...
- bidirectional 5y agoYes, it's also opposite in terms of its correctness.
- fallingknife 5y ago1. no state 2. no side effects And you get most of the benefit of FP in a way that everyone can understand and can use any language.
- dataflow 5y agoIsn't it more like, no mutation?
- tinco 5y agoNot exactly. When using the I/O monad in a pure language like Haskell, your code doesn't directly have side effects, instead you're building a container (a monad) of instructions of what side effect having operations to do, and what should be done with the results. The Haskell runtime then takes this monad and unwraps it layer by layer, each layer executing the side effect having instruction and using the results of the side effects as input for unwrapping the next layer. You could argue that because of this system the language itself is pure and without side effects and without mutation. Note that the effect of this system is exactly the same as a language that does have side effects. They are functionally identical. The nicety of Haskell's purity comes from how the monads allow you to organize your code. By the way, not sure if this is controversial but JavaScript's I/O system is a lot like the I/O monad. I/O doesn't really get executed immediately, and you can't directly operate on the results of I/O. The runtime executes the I/O after all JavaScript's been executed, and you use callbacks to tell the runtime to do whenever the I/O data returns. Of course JavaScript does allow for mutation, so it's not pure in that sense.
- brundolf 5y agoWait, a functor is just a pure unary function? And an endofunctor is just one of those where the argument type and return type are the same? This could have been explained to me years ago, in five minutes? Sometimes it makes me mad that so much confusion (and as another commenter put it, gatekeeping) has been sown in FP circles through the invention of pointlessly-obfuscated terminology for everything (and through - among many in those circles - a lack of interest in connecting the very simple dots that would allow masses of people to understand these concepts). It's like when the medieval Catholic Church refused to print a bible in anything but Latin so that they'd remain the sole authority on its content. Kudos to the OP for cutting through some of that, but shame on those who maintain this status quo. Edit: assuming it really is (roughly) that simple. Some in the comments have suggested parts of the OP were wrong (assuming they aren't just being pedantic), so I'm curious to see discussion.
- tomc1985 5y agoKind of reminds me of an old saying I heard somewhere, that I'll paraphrase here: "novice writers use little words, intermediate writers use big words, and expert writers use little words." Like, it's fun to communicate in technical jargon -- and personally I'm quite proud of the vocabulary I have built up over time -- but you are totally correct in that it serves as a gatekeeper for an in-group to retain its dominance over a given field. There is a lot to be said for effective communication using a simple, base language and reserving obtuse technical terms for areas where one needs to be very specific. There's another point to be made for not inventing new technical terms when existing ones apply. The amount of overlapping terminology in this field is infuriating to me. This is true across all disciplines...
- Littlebigo 5y agoI very much agree with part of your point, especially the novice-intermediate-expert part on jargon. I generally favor wording that is as simple as possible, but no simpler. Sometimes technical precision is important, and when talking to colleagues and other people that are on a similar technical proficiency level as me I prefer concise and informative words. I'd rather say "ARP poisoning" than "network attack", because the latter loses information, but would obviously use the latter to muggles. I don't agree that having a domain jargon that is technical and concise is "gatekeeping" for functional programming. If you are a frontend developer you need to know what the DOM is. If you are a Haskell programmer you need to know what a monad is. The fact that you don't get the Haskell jargon "for free" coming from other programming disciplines doesn't mean that it's "gated", it just means you need to learn. And there are plentiful resources to help you with that, countless "how to understand monads" articles and so on. In my experience, the Haskell community is perhaps the single most welcoming and helpful programming community. There's even a handy guide with big, friendly drawings.
- pcj-github 5y agoCan't resist: https://www.youtube.com/watch?v=ADqLBc1vFwI&t=1s https://www.youtube.com/watch?v=ADqLBc1vFwI&t=1s
- version_five 5y agoYes, this was unfortunately my first thought too when I saw the headline. The video is really funny though. I don't know how popular a meme it is generally, the first and only time I saw it used was this one wrt functional programming and it still makes me laugh every time I watch it.
- SebastianFrelle 5y agoBest laugh I've had in a while.
- jkhdigital 5y agoThere’s a few gaps in this explanation that my deductive completionist brain is looking for. Namely, I’m wondering what kind of thing is even capable of being a monoid and an endofunctor at the same time. Mathematically, a monoid is a set (or collection to be more general) closed under a binary operator (the monoidal product) and with a distinguished identity element. An endofunctor is a mapping from a category to itself, which entails a mapping of each object as well as a mapping of each morphism. So I’m not even sure how to parse the phrase “monoid in the category of endofunctors” because the data required to describe these two things seems completely different.
- dwohnitmok 5y agoThe categorical definition of a monoid is different than the usual algebraic one (although one can be recovered from the other) and usually treats a monoid as a single object (hence "mono-"). In particular, usually a monoid is defined as a single object category (sometimes a "monoid object" is defined inside a category, but that's a different presentation). The usual multiple objects of an algebraic monoid correspond to different arrows/morphisms within a monoid. So for example, while the usual algebraic presentation of a monoid would say the integers form a monoid with an identity element `zero` and normal integer addition forming the monoidal operator, the categorical definition says instead that the monoid is the category that consists of only one element Unit and the morphisms (x => x + 0), (x => x + 1), (x => x + 2), etc. We have an identity morphism (x => x + 0), which when composed with any other morphism does not change it (x => x + 2 composed with x => x + 0 still is just x => x + 2). This is a common pattern in category theory: everything is reduced to composition. So that's a categorical monoid, just a single object with a lot of morphisms and an identity morphism. We can back out the usual algebraic definition by associating with each morphism the "element within" (i.e. associating (x => x + c) with c), but it represents a different way of thinking. We can also talk about a monoid object in a larger category in much the same way. Hence now that we can talk of a monoid as a single object, we can then say that an endofunctor is a monoid (given the proper mappings on an endofunctor, i.e. natural transformations).
- Koshkin 5y ago
- dd444fgdfg 5y agoyou guys are trolling us now with these titles :D
- gaudat 5y agomonadz are monoidz in de gategory of endofunctorz :DDD
- deleted 5y ago[deleted]
- epolanski 5y agoHis monoid definition seems weird, doesn't include identity, and his endofunctor definition seems just wrong.
- lmm 5y agoThis post is very wrong. Being a monoid in the category of endofunctors means something very different from being a monoid in the normal sense (they're related in a category-theoretic way, but the similarity is at a very abstract level). Simple sequences have a lot of structure which mean they are a lot of different things; it is true that sequences are all of monads, functors, and monoids, but the latter structure is unrelated to the former. Contrary to this post, merely being a functor and a monoid does not make something a monad; for example any arbitrary monoid (say, the integers) could be considered an applicative via Const, but is not a monad. Or many other applicative-but-not-monads have monoidal structure, e.g. ZipList.
- momentoftop 5y agoRight. Things could be headed off early where the blog defines a monoid. The definition given is roughly what the average mathematician would call a monoid, but a category theorist would complain saying that it only defines a monoid in the category of sets. But monads are not monoids in the category of sets. They are monoids in the category of endofunctors! So the blog post is going off the rails from here on.
- belter 5y agoThe article is just proving what we all know for a long time about Monads: https://twitter.com/randyshoup/status/992773186239516677?lang=en https://twitter.com/randyshoup/status/992773186239516677?lan...
- rofrol 5y agoGoodstein: Why spin one-half particles obey Fermi-Dirac statistics? Feynman: I'll prepare a freshman lecture on it. He came back a few days later to say: I couldn't reduce it to the freshman level. That means we don't really understand it. https://www.quora.com/What-did-Richard-Feynman-mean-when-he-said-What-I-cannot-create-I-do-not-understand/answer/Mark-Eichenlaub https://www.quora.com/What-did-Richard-Feynman-mean-when-he-...
- deepsun 5y ago> means something very different from being a monoid in the normal sense Yet you didn't say how exactly different. I understand I probably need to know category theory for that, yet nevertheless OP's post was useful, fulfilled some curiosity, but your comment didn't, besides leaving feeling "it's complex", sorry. I'd really appreciate if someone one day wrote as clear explanation of monads as OP's, but at the same time staying correct.
- dwohnitmok 5y agoThis article is playing fast and loose and I think gives a false understanding of what functors and monads are. In particular there is an unwarranted leap here. If `numToStr` is a functor, then `addOne` (the function that just adds one to an integer) should be an endofunctor. So what's the monad? Yet all of a sudden the article jumps to talking about `Array` as an endofunctor! Which is most definitely not a function like `numToStr` or `addOne`. So which is it? In particular, > Of course, as we saw above, Arrays support a map method which allow us to transform the values of the array but do so in a way that returns an Array (the same type as the starting type), making them endofunctors. Makes no sense combined with `numToStr`. What exactly is the `map` function for `numToStr`? It turns out you can unify both of these notions, but you need the language of category theory to do it. But that's overkill for FP. So generally in FP a functor is just a type constructor (a type that takes another type as an argument e.g. `List<A>` or `Option<A>` or `Future<A>`) with an associated `map` function that obeys the "law" that `map`ing the identity function does nothing. The full category theory definition requires a bit more exposition than just thinking of things as sets and functions. In particular you need to talk about two levels of mappings: mappings between categories, which are functors, and mappings between functors themselves, which are natural transformations. A monad is then a functor from a category to itself with two associated natural transformations. If the functor and natural transformations are taken as objects and arrows/morphisms in a category itself, then it forms a monoid. This is why we can also think of a monad as a monoid. This sort of "category-stacking" where mappings between categories are treated as categories themselves where we can then further discuss another level of mapping between them, is the core of category theory.
- jkhdigital 5y ago> This sort of "category-stacking" where mappings between categories are treated as categories themselves where we can then further discuss another level of mapping between them, is the core of category theory. I've started to call it "fractal math". Not to be interpreted as the mathematics of fractals, but rather as mathematics which is itself structured as a fractal (metaphorically speaking, of course).
- IndexPointer 5y agoYeah, it's very confusing. Array is a monad. Then what's the function that takes an array and returns another? Is it map? That can't be because map takes two parameters, not one: the array and a function that it will apply to every element. Something is missing in the explanation. And why is Option a monad? What's the associative function that takes two options and returns another Option?
- btown 5y agoIf you're looking for a not-quite-monad tutorial that answers real-world programming problems, blows the gates off monad-notation gatekeeping, and pokes good-natured fun at the OP title, I highly recommend Railway Oriented Programming: https://www.slideshare.net/ScottWlaschin/railway-oriented-programming https://www.slideshare.net/ScottWlaschin/railway-oriented-pr... https://fsharpforfunandprofit.com/posts/recipe-part2/ https://fsharpforfunandprofit.com/posts/recipe-part2/ for a text version https://fsharpforfunandprofit.com/rop/ https://fsharpforfunandprofit.com/rop/ for the "hub" that discusses how this isn't really a monad tutorial but hints at how you can go deeper - and if you read this before you read the OP you can see how the meta-puzzle pieces fit together! At the highest level, this helped me see that monads are really just Level 2 of "things that help you glue things together that weren't meant to be glued together (particularly if those things emit changes to some external state.)" And that's exactly what the railway/error-handling analogy brilliantly shows. You've probably written almost-monadic things yourself, you just don't know it!
- wheresmycraisin 5y agoJust today, Don Syme wrote up thorough explanation on why he won't be adding type classes and more higher-order-types (or whatever the correct term is) to F#. As someone learning F# and starting to use it in production, I love it because it shows that there is a focus on practical FP even at the very top of the community. https://github.com/fsharp/fslang-suggestions/issues/243#issuecomment-916079347 https://github.com/fsharp/fslang-suggestions/issues/243#issu...
- bern4444 5y agoScott Wlaschin is an excellent resource. His presentations and website are incredible.
- devit 5y agoThe article is completely wrong. The monoid operation is not array concatenation (wtf?) but the monad join operation. Here is a correct explanation: https://stackoverflow.com/a/3870310 https://stackoverflow.com/a/3870310
- epolanski 5y agoThat's actually the only correct part of the blog, arrays form monoids via concatenation and empty arrays. That's algebra tho, which is very relevant to functional programming (monoids capture the essence of composition) in general, but not the right monoids in category theory.
- devit 5y agoOf course they form a monoid with concatenation, but it's not the monoid that makes the monad (which should be pretty obvious since concatenation is not used in the monad operations for arrays).
- lkitching 5y agoThe type of join for arrays is Array (Array a) -> Array a which should concatenate all the inner arrays together.
- gerdesj 5y agoThe article asks: "What's a Monoid". The next header is: What's in a Monoid. If you are going to toss funky sounding words around then please get the basics right. A thing and what's in a thing are rather different things.
- yodsanklai 5y agoFor those who wonder, you don't need to know about category theory to use monads as a programmers.
- deleted 5y ago[deleted]
- edflsafoiewq 5y agoThe basic analogy between them is this: A monoid is something where you take two things and multiply them to get one thing. 2 x 3 = 6 In a monad, you take a doubly-nested thing and "multiply" and get a singly-nested thing: [[a,b],[c]] => [a,b,c] The monoid laws say that, though you can multiply in different ways, it doesn't matter what order you do it, the end result is the same: (2 x 3) x 4 = 2 x (3 x 4) The monad laws say the same thing: the order you do the "un-nesting" doesn't matter: Inner-most first: [ [[a,b],[c]], [[d]] ] => [ [a,b,c], [d] ] => [a,b,c,d] Outer-most first: [ [[a,b],[c]], [[d]] ] => [ [a,b],[c], [d] ] => [a,b,c,d] ----- If you take the definition of a monoid, which has stuff like M is a type multiply : M x M -> M (multiplies two elements) what it means to do it "in the category of endofunctors" is it changes into M is an endofunctor, a is any type, Ma is M applied to a multiply : M(Ma) -> Ma ("multiplies" doubly-nested element) and when you do these changes for the whole definition of a monoid, what you get is exactly the definition of a monad.
- BrissyCoder 5y agoHands up if you've never actually seen FP out in the wild doing something. Not saying it's not out there or useful - just saying that after 20 years I'm yet to come across it once.
- yawaramin 5y agoEver use Facebook? WhatsApp? Discord? Telephones? Docker? Amazon EC2? Bought something in a Walmart store or on their websites? etc. etc. Some of their core, critical parts are written in functional programming languages. Just because you don't see FP out in the wild being conspicuous, doesn't mean it's not there ;-)
- BrissyCoder 5y agoWhich parts in particular? Genuinely curious.
- yawaramin 5y ago- Facebook: spam filter implemented in an efficient data access language/tool called Haxl: https://engineering.fb.com/2014/06/10/web/open-sourcing-haxl-a-library-for-haskell/ https://engineering.fb.com/2014/06/10/web/open-sourcing-haxl... - WhatsApp: famous for being written in Erlang, a functional programming language, and processing more messages a day than the entire global SMS network with a team of 50 backend engineers - Discord: handling extreme amounts of chat/call traffic using Elixir, another functional programming language based on the same tech as Erlang - Telephones: telephone switches from Ericsson (and in fact, internet switches from Cisco) use Erlang - Docker: core virtualization component for macOS (hyperkit) written in OCaml - Amazon EC2: another core virtualization component of all computes, parts of the Xen hypervisor, written in OCaml
- Littlebigo 5y agoWell... chances are you've made thousands of phone calls through switches running Erlang. You may have used Emacs, Discord, Facebook, Pinterest, Spotify, Font Awesome, xmonad or visited web sites running Elm or an Elixir backend... or even driven a Volvo. Here's a list of companies using Haskell, with similar links to other functional languages: https://github.com/erkmos/haskell-companies https://github.com/erkmos/haskell-companies. It includes names like Facebook, Tesla, Klarna, Target and Kaspersky. Not to mention the FP paradigms used in Python, C++ and other languages. In fact, if you've never come across FP "in the wild doing something" then I suspect you're living very much off-grid.
- arthurcolle 5y agotypo, second mention of endofunctor
- yawaramin 5y ago> This phrase is the cheeky line to (somewhat) formally define the monad It's actually a satirical joke[1] that people started taking way too seriously. Honestly, imho people should never use this line when explaining monads. It's like saying 'C is a purely functional programming language!' because Conal Elliott, around the same time, wrote[2] a parodic blog post making fun of purely functional programming zealots. [1] https://web.archive.org/web/20210824072932/https://james-iry.blogspot.com/2009/05/brief-incomplete-and-mostly-wrong.html https://web.archive.org/web/20210824072932/https://james-iry... [2] http://conal.net/blog/posts/the-c-language-is-purely-functional http://conal.net/blog/posts/the-c-language-is-purely-functio...
- sfsffgrgd 5y agoCome onnn. The phrase that forms the title of this post is very close to what (CT giant) Saunders Mac Lane wrote, quite seriously. In fact it's missing the word "just"! Iry was inspired by Mac Lane, but you seem to have got the wrong end of the stick on the actual status of these words. See, for example, https://stackoverflow.com/a/3870310/14768587 https://stackoverflow.com/a/3870310/14768587
- yawaramin 5y agoI am obviously talking in the context of programming, not abstract math ;-) In this context, it's quite obvious that I am correct. Programmers around the world wouldn't have been perplexed for a decade because of a labyrinthine quote from Mac Lane's Categories for the Working Mathematician.
- momentoftop 5y agoConal Elliott wasn't making fun of pure functional programming zealots. Elliott is a pure functional programming zealot, and was making fun of Haskellers who defend the IO type as a purely functional way to express effects. He thinks the IO type sullies Haskell here, and that we should have picked a different representation for effects (historically, that was true FRP, something he conceived with the late Paul Haduk).
- scrubs 5y agoSince when did writing words then defining those same words become a big deal? And doing it wrong? Let's not confuse jargon with understanding or getting things done.
- bern4444 5y agoWow, this was unexpected. Like many, I'm still learning a lot of this - especially the formal terminology and the distinctions between the mathematical and computational variances of these ideas. It can be tough to push past the more intense and techincal jargon and I enjoy writing about these ideas to document my learnings for myself and to try and make it more accessible to others. I'm happy some found it useful and for the discussion here where people can help correct and inform parts that aren't as sound.
- flebron 5y agoI've always found the definition of monoid objects in a category of endofunctors to be tougher to grasp than the Kleisli-category definition of a monad, at least if one is being formal about "monoid object", and checking that the necessary diagrams commute. Given a functor m of Hask, we define a squiggly arrow ~>, where a ~> b is a -> m b. If these ~> are the arrows in some category (which we call the Kleisli category for m), then we call m a monad. Here id :: a ~> a in that category is what we call return :: a -> m a, and the composition (.) :: (b ~> c) -> (a ~> b) -> (a ~> c) in that category is used to create bind :: m a -> (a -> m b) -> m b, where bind x f = (.) f (const x) (return ()), where (.) is the squiggly arrow (.) we just mentioned. Bind is what's spelled >>= in Haskell, and is what's behind the "x <- f" do-notation.
- Xen0byte 5y agoI don't agree that a transformation which takes an int[] and outputs a string[] is an endofunctor. Yes they are both arrays, but they are different types.
- yakubin 5y agoIt depends on the category. You can have a category of arrays of ints, but you can also have a category of arrays.
- jesuslop 5y agoFor me when I was learning this the first problem was to grab what Mac Lane intended to say with "monoids" exactly (in monads are monoids such that blah) since the default notion from algebra didn't match (unital semigroup). It turns out that he is speaking of monoid objects, which is a technical term as in here [1]. There it describes monoid object in a monoidal category, which is an unfortunate clash of two monoid-sounding things that need to be thought independently. One clarifies first what is the monoidal category, and only then asks what a monoid-object in that category is. In our case one starts with an arbitrary category C. The category of endofunctors has as objects functors F:C->C, and as morphisms natural tranformations mu:F1->F2. Endofunctors always compose, and that gives the endofunctor category a monoidal category structure: The monoidal product, or in other words the tensor product is the composition of endofunctors. One checks that this monoidal product verify the monoidal category axioms. So then one has established what monoidal category we talk aboout. It is in that monoidal category where one consider monoid objects, and then notices that they correspond to monads. [1] https://ncatlab.org/nlab/show/monoid+in+a+monoidal+category https://ncatlab.org/nlab/show/monoid+in+a+monoidal+category
- 2OEH8eoCRo0 5y agoAs an outsider- the amount of disagreement in this thread speaks volumes.
- fugtkcfk 5y agoI don't know if you mean that you are an outsider to HN or an outsider to functional programming. The problem in this thread is not that monads are controversial or poorly understood. The problem is that there is a strong selection effect: the thread is populated by people for whom the topic of monads is relatively new, and who think that this discussion is worth having in this context. People who are "productive" with monads already know exactly what the structure is (it's not complicated) and they're unlikely to want to enter this discussion. They just have better things to do than engage with the misconceptions of "learners" on the Internet. HN in general suffers from posters who write confidently about things they don't fully understand. This tends to drive genuinely competent people away from the site. It affects politics as well as tech discussions. The problem isn't monads, it's the denizens of HN.
- deepsun 5y agoSo we cannot talk about a type being monad without also saying under what function? E.g. Arrays are monads under concatenation. So why people then say easily "Option type is monad" without stating under which operation? I assume Option is monad under "all" and "any" function, but not sure.
- edflsafoiewq 5y agoYes, but its usually obvious which one is meant, so you don't bother saying under what operation. Option is a monad under the same concatenation as Array, just think of them as arrays that always have length 0 or 1.
- deepsun 5y agoHow to concatenate Option-s? Btw your comment seems to contradict another sibling comment.
- edflsafoiewq 5y agoLike I said, view them as an array with 0 or 1 element and do it just like for arrays. There are only three possibilities: [] => [] [[]] => [] [[a]] => [a]
- lkitching 5y agoA monad is a triple: 1. A type constructor M of a single argument 2. A function of type a -> M a 3. A function of type M (M a) -> M a subject to the monad laws. So the 'array monad' is the triple (Array, \x -> [x], Array.concat) and the 'option monad' is the triple (Option, \x -> Some(x), \x -> match x | Some(o) => o; None => None). Saying a type 'is' a monad is imprecise but just means it has an associated monad instance. I've never seen a type with multiple monad instances but I don't know if there could be one.
- deepsun 5y agoWow that's clearer. I wonder if just a list of examples (and counter-examples) would be enough to explain monads (preferrably with configurable syntax for Haskell-deprived folks). Btw, I think you got a mistake there, in the third part of Option should be "Some(Some(o)) => Some(o), Some(None) => None, None => None", otherwise o can be not an Option at all.
- still_grokking 5y agoSorry I need to rant, that's just a too terrible article. It makes no sense at all to try to explain that stuff in a language lacking higher kinded types. All you can do there (without awkward encodings) is creating instances of those abstractions. You can't create the abstraction as such! A quite straight-forward explanation of the "monoid in the category of endofunctors" thing can be found here: https://blog.rockthejvm.com/monads-are-monoids-in-the-category-of-endofunctors/ https://blog.rockthejvm.com/monads-are-monoids-in-the-catego... Even the linked explanation is a "quite 'simple' one for that topic" it's still way more involved than what was shown in the article we're discussing here. That Scala stuff is actually correct, this one here isn't even close. Sorry for the quite negative comment but imho there isn't anything else to add. Before writing a blog post about something one should get at least some basics. Things like: I need HKTs to express functors and such… As I didn't see the given link here I think my comment makes a useful contribution even it doesn't bring anything else to the table; besides some rage about "very wrongly explained math". :-)