367 karma · joined February 10, 2012
If monads are design patterns, then why not rings (Num typeclass), which allow to use addition and multiplication in different contexts? If function composition is a design pattern, then why not function application? If chaining with '>>=' is a design pattern, then is using a semicolon a pattern too? If 'fold', 'map' are patterns, then why not 'sin' and 'cos' are? What is the difference? There's a "pattern" that after sine you put a number; there is also a "pattern" that after a fold you put a function. Thinking that higher-order functions are special is contrary to the spirit of functional programming. Functions and numbers are the same class of citizens, and a function taking a function should not be treated differently from one that takes a number.
Bare names of often-used library functions or language constructs should not be considered patterns, unless they occur as parts of repeating snippets. In this case, you should refactor or encapulate. If you cannot, this is a language flaw. It sucks if you have to type "x = new T(); try { ... } finally { delete x; }" each time. If your language allows to write "using (x = new T()) { ... }" then the pattern is eliminated.
Perhaps there are some "design patterns" in FP, but examples I find often are very weak. One thing that I would count as a pattern is "lift . lift . lift" used in Haskell in monad transformers.
Subset-sum can be approximated within 1+epsilon for any requested epsilon>0 [a PTAS]
MAX-3SAT can be approximated within 8/7 and not better. Vertex cover can be aproximated within 2 and its not known if that's optimal.
Set cover can be approximated within O(log n) and not better.
Clique and TSP have no sensible approximation.
I would argue that potentially a loss of factor 2 is not an order of magnitude away from optimal. I don't know what is the situation for markets.
These two are incompatible. Once you state you are interested in worst case, stating that the number of floors follows a uniform distribution is irrevelant, and IMO confusing; the only relevant thing is that every floor is a possible candidate.
In an ideal world, tests would be subsumed by types, but in reality tests can cover things that types do not.
This error can be caught if you put units of measure into type system. F# can do this, and addition function will have type int<a> -> int<a> -> int<a> while multiplication int<a> -> int<b> -> int<a * b>; for example, int<m/s> -> int<s> -> int<m> might be a function taking velocity and time, and returing distance. I think Haskell has libraries for this.
Similarily, add x y = x - y would be detected if (-) required a group, while (+) worked for monoids only.
However, it would be rather hard to create a type system detecting a typo in:
quadruple x = 3 * x
What is not accurate in that post?
http://www.reddit.com/comments/arc79/reddit_i_got_the_best_p...
No! Please see "Beating the Averages" [http://paulgraham.com/avg.html] (skip to "The Blub paradox" for tldr)
It it true that a lot of discussion here is pointless evangelization and bashing, but the argument "programming language does not matter, only the programmer" is even worse. If that was true, there would be no difference between a C# programmer and a Visual Basic programmer. Languages would stay the same with no initiative to change. Yet they do change and evolve. Programming languages vary in power, even though they are Turing-complete.
Problem 2: You are delaying the unevitable; it's nice to use new features of the language, having to code in old versions is a pain for developers. Small continuous upgrades are easier to handle than rare gigantic ones.
The semi-official motto of Haskell is "Avoid success at any cost", not world domination. It is enough as a tool for hackers, not for everyone. Haskell expands extremely slowly, yet steadily.
> If you want to use these languages, you have a choice between (a) learning the theory, and (b) not fully understanding the tool you're using.
Please bear in mind HM is only a basic idea of how Haskell type system works. Current inner workings of GHC type checking are described in 80 page research paper on OutsideIn(X), http://www.haskell.org/haskellwiki/Simonpj/Talk:OutsideIn. I never read more than half a page from this. Yet I can use GADTs, type families, existentials, rank-2-types and so on with no trouble. I don't think Haskellers who did not read those 80 pages are "not fully understanding the tool they're using".
Why should I know theory - OutsideIn(X), HM, category theory etc., to "fully understand" the tool? Intuitive understanding gained by practice is enough.
> By "debugging" I didn't just mean tracing. I meant one of the most basic tasks of the programmer - interpreting and responding to error messages. Is there a single error message shown or explained in LYAH? If so, I missed it.
Yes, although not much; grep for "error" in http://learnyouahaskell.com/starting-out#babys-first-functio... or other chapters.
I could code comfortably in Pascal long before I knew how exactly does "expecting a semicolon, found a number" arise. I could code comfortably in Haskell many months before learning HM as well. You know what to do when you see "no instance for Num Char" as well as you know what to do with that parsing error. No need to think about unification or parsing, a kneejerk reaction is enough.
> I refuse to believe that Haskell programmers are so godly that their programs work the first time they're typed in.
Of course that's false -- but once a Haskell program is typed and compiled, there are much larger chances that it will work first time compared to, say, Java.
BTW: Debugging is much less used in Haskell, this is not a strong objection to LYAH.
"it's not for me" is not a valid excuse, it means you cannot handle the tool. This is your fault. A valid excuse is "it's not for my application domain".