1,132 karma · joined January 2, 2012
> Anything that needs rewriting a memory address without losing time by allocation and garbage collection.
ST gives you mutable references. Or just use IO.
This made me curious, could you list some?
You can do that in a pure language as well (i.e. ST monad.) Purity shouldn't be given up lightly.
If C is that bad at managing complexity (and complexity doesn't only arise from bad design choices, some problems are inherently complex) then it should be used as rarely as possible, period.
It's not about idealism, it's about ill-placed, almost comical elitism ("C is a low-level-hacker language and only real programmers use it" while a 3rd grader could understand pointer arithmetic) to the point of rather spending 5 days writing bug-ridden code in C instead of 5 minutes in whatever else, just because it's the right way.
It's ridiculous.
... exactly.
float *float_ptr; float_ptr += 1;
is no more confusing than
float float_ptr[...]; float_ptr[1];
> no more overflows, no more pointer screwups, no more forgetting to free the memory, because you'll know exactly what will happen in the chip and the memory when that code compiles
To whoever wrote this: are you ready to share the code of a sufficiently complex program in C (or assembler, why not) you wrote and pay $100 for every "pointer screwup", buffer overflow, memory leak and generally every bug people find, which could have been prevented by a strong type system or borrow checking and other such complicated features?
You could use mutable arrays in Clojure the same way you could use immutable arrays in Python (yet nobody is calling Python a functional language.)
Still, I agree that functional mostly means "language with closures and immutable data" in the mainstream, but in the context of this post I'd say it's not that hard to guess that the authors meant purely functional.
They should've probably said "FP-only" (i.e. pure) languages to exclude imperative languages that merely support functional programming constructs, like Clojure, Erlang, etc.
I agree, many of the concepts that are useful in pure languages (i.e. monads) are not that practical in imperative/impure or dynamic languages (at the cost of reduced ability to reason about your program.)
> And if the list is comprised of Haskell-centric jargon for more generic notions, that's obviously grounds for criticism.
It's the other way around - the items on this list are the more generic concepts [0]. Less expressive languages lack the (practical) ability to reason about those concepts generically, hence the need for more specialized constructs, like i.e. streams, transducers, etc.
Your "hideously complicated type theory" is many peoples' "hideously horrible paren-based syntax" - i.e. Lisp. So, how many people don't learn Lisp only because of its syntax? I'd say a lot.
Many of the concepts make sense when having an explicit type system, so if you want types you may want to learn them.
Others I suspect you are already using, even if you don't know them by name. Have you ever used streams? Congratulations, this is what codata is.
By pressing Cmd-D the user is prompted to enter a tag, and after that a .webloc (essentialy a link) file is created in a subfolder determined by the tag name.
The location to store the files in can be configured (i.e. some Dropbox folder, so that bookmarks are automatically shared).
This has the advantage that it's:
* instantly searchable using the same search interface like everything else (Spotlight)
* forwards compatible - no need to import/export bookmarks when switching browsers
* distributed - bookmarks are instantly and automatically distributed (Dropbox)
* automatically backed up forever (Dropbox)
I'm not using Firefox right now, so the extension might be out of date. Maybe time to port it to Chrome/Safari :)
[0] https://github.com/pkamenarsky/fbookmark
[1] https://addons.mozilla.org/en-US/firefox/addon/pentadactyl
For the time being, make a helper function:
ixWithString :: String -> Int -> Array a -> a
check the bounds inside and error out with a custom message when the index is outside the array bounds.
It's even impossible to upload a package to the official repository containing JavaScript code without prior approval, because the native code may crash!
[0] https://pursuit.purescript.org/packages/purescript-arrays/3....
This is much faster than writing a large chunk of code, playing around in the REPL thinking everything is ok, only to realize one week later that you didn't think through some core aspect of your design and then having to refactor a sizeable piece of your codebase.
> The last message I get was something like "Array.Array: Index out of bounds". Program crashed. No idea where the error originated.
It is an unfortunate historical artefact that there are still partial functions (i.e. functions that may crash) in the Haskell base libraries. It is generally advised to avoid such functions, but this is not very clearly communicated to newcomers to Haskell.
For example, Elm, a language largely inspired by Haskell, doesn't have partial functions. This is why it prides itself in "not having any runtime errors in production" (excluding things like compiler bugs or unsafe JavaScript libraries, of course).
All I could do is collect metrics like lines of code and intentionally vague experience reports from former colleagues who are still there, but I guess that's hardly gonna convince anybody.
In most cases management isn't qualified to make technical decisions. Managers rarely see the bigger picture.
I've worked on a Haskell project that worked, never crashed, was lightning fast and was meeting deadlines for new features without a problem. Then higher management decided to throw away probably around 7-10 man-years and rewrite the whole thing in Java, quite literally "just because Java". We even had a consultant from FP complete come over to take a look at our codebase and talk in front of management about the advantages of a mature codebase in Haskell. Management didn't even come.
Abandoning Haskell, in my case, had absolutely nothing to do with its technical merits and everything to do with incompetent management. When I left one year after they started rewriting the project in Java (I was staying to help maintain the Haskell code while the transition was happening) everything was buggy as hell, slow and unmaintainable. Not to mention that half the Java guys they hired had already left again.
The opposite is true: here Haskell helps to find the right data structures/abstractions incredibly fast. The ability to quickly construct and reconstruct a high-level skeleton of your program without actually having to implement anything makes prototyping much easier and faster than in comparable dynamic languages.
> But then you hit a wall. Laziness makes for brutal debugging.
Laziness can sometimes surprise you in bad ways, but it's not like it's impossible to debug.
> Singly linked lists actually suck.
Just replace them with the right data structure then? Even for big codebases and fundamental program abstractions that's a 15min job, because of types.
> Performance optimization is a black art.
I agree. But then again - you don't have to write everything in Haskell. Writing the critical 1% in C, testing the shit out of it and calling it from Haskell is absolutely fine.
Even keeping two different views in sync in different parts of an application without a framework is so much work it's not worth the effort, let alone building a whole SPA.
But to each their own.
I can see where his frustration stems from though, getting a response like "I don't want to unless you show me a use case" when clearly presented with a use case after spending weeks trying out someone's language can be infuriating. As I said, not very professional, but understandable imo.
This is definitely true. The firmware on your phone is probably written in assembler.
> Instead of sitting on such a high horse the more constructive approach is to outline the shortcomings, implement the solution, and contribute it upstream.
You complain about sitting on high horses while the author did exactly that and got a high-horse response from Evan.
> Comparing a language that programmers use every day to ship working solutions to another one that has considerably smaller mindshare and community
Are you talking about PureScript? Judging by GitHub popularity I'd say both languages are about equal in that regard, but who knows.
* Thing.map :: (a -> b) -> Thing a -> Thing b instead of deriving Functor (or Applicative, Monad, Generic, ...)
* showThing :: Thing -> String, readThing :: String -> Maybe Thing instead of deriving Show/Read
* decodeThing :: Json.Value -> Maybe Thing, encodeThing :: Thing -> Json.Value instead of deriving From/ToJSON
* lenses definitions instead of makeLenses ''Type
* things like
update (Event childEvent) model -> let (m, fx) = Child.update childEvent model.child in ({ model | child = m }, Fx.map Event fx)
instead of using lenses* append :: (a -> a -> a) -> (b -> b -> b) -> (a, b) -> (a, b) -> (a, b) instead of reusing the Monoid instance on tuples
* toDyn :: (a -> TypeName) -> a -> Dynamic, fromDyn :: (a -> TypeName) -> Dynamic -> Maybe a instead of deriving Typeable
* things like type StateLogger st = { log :: [st], current :: st } and then writing StateLogger.map, StateLogger.return, StateLogger.andThen, StateLogger.modify, StateLogger.tell instead of just type StateLogger = WriterT [st] (State st) and getting all of that for free... not only that, but now you can use lenses for manipulating a deeply nested state as well, because guess what, Control.Lens.Zoom is written generically
And those are just the possible, but cumbersome things. There's stuff that's impossible to do:
* free monad custom DSLs
* GADT datatypes for typesafe request/response communication
* existential quantification in ADTs
Now this is very down-to-earth get-things-done Haskell code. All these things are there because they make the code simpler, easier to understand and eliminate repetition.
Elm is particularly easy to pick up for people coming from Haskell. Maybe not in 15 seconds, but 15 minutes is a totally reasonable estimate.
The author can without doubt write a large project in Elm. His complaints were about missing the conveniences of abstraction Haskell-like languages provide, and he is more than qualified to talk about it.
Decomposing records into tuples of comparables has probably crossed his mind :)