Live data from Hacker News

Dueling Rhetoric of Clojure and Haskell

tech.frontrowed.com

31–40 of 107 posts

Re: Dueling Rhetoric of Clojure and Haskell

#31
post #15

Earlier quoted context omitted.

> A dynamically typed language is a statically typed language with precisely one type. While technically true, saying this is about as useful as saying "You can do anything in any Turing-complete programming language."

The point is, types give you an option to encode invariants at compile time. You can choose to use this to your advantage, or not use it at all(use ByteString for everything). With dynamic types(or just one type), you don't even have the option to do this.

There's just one type at compile time, but many more at runtime. This is still a strongly typed language. The only problem is our static analysers are too dumb to prove things without providing ample explicit hints, or changing the way we code to restrict certain ambiguities that it can not resolve at compile time. Haskell has chosen to try and push the boundaries of such static analyzer, but there's still limits, and it can't infer everything, and still restricts certain designs. I admire it for its efforts.

Clojure has a different strategy, it creates a new time, REPL time. So you can test your types at REPL time. Not when it compiles, but a little before it runs. It won't prove what you don't try though. So in practice, its using a statistical model where the programmer is the heuristic. You best guess the edge cases, and try them at REPL time. This will not catch all static errors, but will also catch some runtime errors. So it creates a disjoint set of errors that it catches. This is a trade off. Static types and REPL time will catch some of the same things, but also different errors.

Now both adding static type info, and doing REPL time testing comes to a cost to the programmer. Its one more thing we have to do. Some like me, fond more value most often at the REPL, it helps me explore and innovate my code, and is just more fun to me. I also prefer the kind of bugs it catches. Others think the opposite.

What most people seem to agree on though, is that doing both is way too much effort. That's why you don't have REPL time be a popular activity in Haskell, or core.typed be popular in Clojure.

Re: Dueling Rhetoric of Clojure and Haskell

#32
"If EDN is an improvement over JSON, then it is marginal at best."

Why is it only a marginal improvement? It adds considerably more semantic information.

"Utilizing EDN also promotes a lot of invisible coupling. Some may tell you that dynamic types don’t couple, but that is incorrect and shows a lack of understanding of coupling itself. Many functions over Map exhibit external and stamp coupling."

Coupling implies a bidirectional connection. Functions rely on data types, but not vice versa.

Re: Dueling Rhetoric of Clojure and Haskell

#33
post #9

A dynamically typed language is a statically typed language with precisely one type. It is extremely easy to use haskell in "dynamic mode". Just use `ByteString`(or Data.Dynamic for safety/convenience) for all your data. Types just present a way to encode some statically known guarantees about the structure of your data/code. You are free to not encode any properties if you want to. But it is very rare that the data…

"A dynamically typed language is a statically typed language with precisely one type." You still have types; they're just not checked at compile time.

You can have dynamic "type-tags" for your unityped language too. That is what is done in the EDN ADT described in the article.

Re: Dueling Rhetoric of Clojure and Haskell

#34
post #8

Earlier quoted context omitted.

The fact that Haskell is smarter than me is exactly why I have been keeping at it! There is no fun left if you know all the overarching principles of a language, and you realize it still doesn't solve your problem. This happened to me when learning Python, this is also why I don't really look at Go or Rust. They're good languages, I might use them at a workplace someday, but you can get to the end of their semantics,…

The fact that Haskell is smarter than me is exactly why I have been keeping at it! I tend to think of Haskell as an eccentric professor. Sometimes it's brilliant and what it's developed lets you do things that would be much harder in other ways. Sometimes it just thinks it's clever, like the guy who uses long words and makes convoluted arguments about technicalities that no-one else can understand to look impressive,…

No, not "thinks it's clever", but overly clever, yes, often.

Re: Dueling Rhetoric of Clojure and Haskell

#35

The dueling rhetoric is the same rhetoric that has been around for decades: Some people really feel type systems add value; others, feel it's a ball and chain. So which is it? The answer is probably "yes." We should all believe by now since history has proven this correct. Most of the time you start with no type system for speed. Then you start adding weird checks and hacks (here's lookin' at you clojure.spec). Then…

Most of the time you start with no type system for speed. Then you start adding weird checks and hacks (here's lookin' at you clojure.spec). Then you rewrite with a type system.

You seem to be in the camp of gradual types. Which Clojure falls more into, though experimentally. Racket, TypeScript, Shen, C# or Dart are better examples of it.

make me smart enough to understand how a statement like "a monad is just a monoid in the category of endofunctors" can radically change how I implement marginably scalable applications that serve up JSON over REST.

That's the thing, it doesn't radically change it. Static types are not powerful enough to cross remote boundaries. Also, monads don't need static types, and fully exist in Clojure. Haskell is more then a language with a powerful static type checker. Its also a pure functional programming language. It will help you if you don't complect static types with functional programming. There's more design benefits from functional programming then static types. Learning those can help you write better code, including Json over rest api style applications.

Clojure and Haskell are a lot more similar then people think. Clojure is highly functional in nature, more so then most other programming languages. So is Haskell. Haskell just adds a static type checker on top, which forces you to add type annotations in certain places. Its like Clojure's core.typed, but mandatory and better designed.

Re: Dueling Rhetoric of Clojure and Haskell

#36
post #8

Earlier quoted context omitted.

The fact that Haskell is smarter than me is exactly why I have been keeping at it! There is no fun left if you know all the overarching principles of a language, and you realize it still doesn't solve your problem. This happened to me when learning Python, this is also why I don't really look at Go or Rust. They're good languages, I might use them at a workplace someday, but you can get to the end of their semantics,…

I love how I just keep learning Haskell, and keep improving, despite how much I already did it. That said, Python is also smarter than me. The possibilities with monkey patching and duck typing are endless. But differently from Haskell, Python is not a good teacher, so I tend to only create messes when I go out of the way exploring them.

> That said, Python is also smarter than me. The possibilities with monkey patching and duck typing are endless.

Don't do it, 99.9% of the time. It's that simple.

There is seldom a reason to use more than just defs - and a little syntactic sugar (like list comprehensions) just to keep it readable.

Even the use of classes is typically bad idea (if I do say so). Just because: there is no advantage to using it, except when everything is super dynamic. And if that's the case, I suggest that's a smell, indicating that one is trying to do to many things at once, not properly knowing the data.

Nevertheless using classes (or any other superfluous feature) makes everything more complicated (less consistent - need new ways to structure the program, new criterions whether to go for a class or not to or where to bolt methods on,...).

Don't use "mechanisms" like monkey patching just because they exist. They are actually not mechanisms - just curiosities arising from an implementation detail. The original goal is simplicity: Make everything be represented as a dict (in the case of python)

> The possibilities with monkey patching and duck typing are endless.

I think there are many more "obvious" ways to do things in Haskell than in Python just because you as a developer need to draw the line between static and dynamic. And if you later notice that you chose the line wrong, you have to rewrite everything.

In Python - or any other simple language - there is typically one obvious way to do things. At least to me.

Re: Dueling Rhetoric of Clojure and Haskell

#37
post #9

A dynamically typed language is a statically typed language with precisely one type. It is extremely easy to use haskell in "dynamic mode". Just use `ByteString`(or Data.Dynamic for safety/convenience) for all your data. Types just present a way to encode some statically known guarantees about the structure of your data/code. You are free to not encode any properties if you want to. But it is very rare that the data…

> A dynamically typed language is a statically typed language with precisely one type. While technically true, saying this is about as useful as saying "You can do anything in any Turing-complete programming language."

No, it's really not equivalent to cracks about Turing completeness.

Doing "dynamic" typing in a static language requires me to add all of 5 characters, e.g. ": Any"

Doing static typing in a dynamic language requires me to write a type checker.

These are nowhere near the same.

Re: Dueling Rhetoric of Clojure and Haskell

#38
post #21

Earlier quoted context omitted.

I'd gladly storm into the breach with you :) Hopefully we all agree that static types and dynamic types are useful. Those who use hyperbole are attempting some form of splitting. I think the point where we disagree is what the default should be. The truth is this discussion will rage on into oblivion because dynamic types and static types form a duality. One cannot exist without the other and they will forever be ent…

Well, I think that static types are much more useful than dynamic ones. Static types allow you to find errors with your program before execution and that is very important. And if you are going to go through the effort of defining types, it is much better to use static types because then you get this additional error checking. Furthermore, with static types the compiler can help in other ways, e.g. by organizing your…

Dynamic types are definitly more useful. That's why since the last 40 years, we've almost never once had a language without it. That's why Haskell also has dynamic runtime types. Erasing them at runtime, and stopping to check their validity at runtime would be folly.

Static types are an extension, they say, do not allow types to only be defined at runtime when possible. Its not always possible, which is why static typed languages also include a runtime dynamic type system.

The debate is if the benefit of static checks on types outweighs the negative of having to spend time helping the type checker figure out the types at compile time, and limiting the use of construct that are too dynamic for the static checker to understand at compile time. That's the "dichotomy". To which someone proclaims: "Can we have a static type checker which adds no extra burden to the programmer and no limits to the type of code he wants to write?" To which OP has missed the point entirely and simply shown that you can spend more time giving the Haskell type checker info about EDN, and gain nothing since its now neither useful, nor less effort. Which was a bit dumb, but he did remark that he did it for fun and laughs, not for seriousness.

Re: Dueling Rhetoric of Clojure and Haskell

#39
post #31
post #15

Earlier quoted context omitted.

The point is, types give you an option to encode invariants at compile time. You can choose to use this to your advantage, or not use it at all(use ByteString for everything). With dynamic types(or just one type), you don't even have the option to do this.

There's just one type at compile time, but many more at runtime. This is still a strongly typed language. The only problem is our static analysers are too dumb to prove things without providing ample explicit hints, or changing the way we code to restrict certain ambiguities that it can not resolve at compile time. Haskell has chosen to try and push the boundaries of such static analyzer, but there's still limits, an…

> That's why you don't have REPL time be a popular activity in Haskell

Is it not a popular activity to use the Haskell REPL (ghci)? I though it was pretty common to use it when developing code, though I admit I don't have any hard data.

Re: Dueling Rhetoric of Clojure and Haskell

#40
post #37

Earlier quoted context omitted.

> A dynamically typed language is a statically typed language with precisely one type. While technically true, saying this is about as useful as saying "You can do anything in any Turing-complete programming language."

No, it's really not equivalent to cracks about Turing completeness. Doing "dynamic" typing in a static language requires me to add all of 5 characters, e.g. ": Any" Doing static typing in a dynamic language requires me to write a type checker. These are nowhere near the same.

Clojure has type hints, I can add ^int to a symbol and get some “static typing”. That is: shitty static typing. However, this is about the same as the average Any type in a static language. In order to implement a good Dynamic type, you’d need to implement reflection, caching dynamic dispatch, etc. Haskell’s Typeable is an OK implementation, but not nearly as good as say the JVM’s or JavaScript, despite their many flaws.
Post reply on HN