Live data from Hacker News

Dependent Haskell

serokell.io

81–90 of 92 posts

Re: Dependent Haskell

#81

Earlier quoted context omitted.

When I see this definition, I scratch my head and wonder why this isn't a different way to introduce object orientation, generics, c++ parameterized templates and such.

The key difference with C++ templates is that in C++ you can't have a type parameterised by a value that's only know at runtime, e.g. a std::array where N is read from stdin. In a dependently typed language, you can. Object orientation is a different matter entirely; in the sense it implies Java-style class-based inheritance, it's almost in the opposite spirit to dependent types, as such late-binding (virtual methods…

[deleted]

Re: Dependent Haskell

#82
post #74

Earlier quoted context omitted.

Right, the difference is to some degree syntactic, but then, so is most programming ("it's just math"). The most significant difference, as it appears to me (note that I've done only a bit of research into refined types, and practically none into dependent types), is that dependent types means building top-down whereas refined types means building bottom-up. Dependent types: everything is proved, by hand, by the user…

OK, I think I see where you're coming from. I don't think the distinction you make is a useful one. > A concrete difference would be, in dependently-typed language, you define a list type as [...] Coq is a dependently typed language, and while it has a definition like this for some thing (called vector, maybe? I forget), the definition for lists in the standard library is not dependent, and length is a separate funct…

Cool, very interesting. I need to look into Coq again! Maybe it's closer to what I want than I thought!

Re: Dependent Haskell

#83
post #63
post #22

Earlier quoted context omitted.

Academically, both reference counting (C++, Swift, some patterns in Rust) and tracing garbage collection (Java, C#) fall under the umbrella of garbage collection.

The important distinction, then, is obligate garbage collection. Can I write a substantial program that does, and needs, no garbage collection of any kind? In C++ and Rust, yes, trivially, every day. The distinction matters because without obligate GC, you get the benefit of destructors (or in Rust, the Drop trait), and have the tool for resource management of every kind, usually written "}". Reference counting GC is…

This isn't true if you've actually seen production Rust code, but the point is irrelevant to the issue of swift being GC'd - it is.

Re: Dependent Haskell

#84

Earlier quoted context omitted.

> Haskell is simple That it might be, but it sure as hell isn't easy. Brainfuck is simple, but nobody would choose to write a real project in it. Most programmers struggle trying to understand what a monad is. That's not easy. The free monad is not easy. Monad transformers are not easy. Understanding foldable/traversable/arrows/applicate is not east. Lens is/are not easy. I have personally worked with dozens of progr…

Easy for whom? Finding Haskell difficult is nothing to be ashamed of. However it's going to appear more difficult than it ought to be if you're approaching it as an experienced programmer with strong opinions. It can be humbling to realize that there's a whole branch of programming you're completely new to and know little about. It's going to be difficult to climb that mountain and you will feel like a beginner again…

> Easy for whom?

Nearly everyone I have met and/or worked with.

> Finding Haskell difficult is nothing to be ashamed of

Agreed.

> It can be humbling to realize that there's a whole branch of programming you're completely new to and know little about.

Agreed.

> It's worth the effort!

To learn it? Sure. To use it? I disagree. I was more unproductive with Haskell than I've ever been with C, which is usually the language I love to bash on. I can look up opcodes and write assembly faster. "Ah, but with experience!" - I don't see why I'd bother.

I write mostly functional code in any language I'm working in as it is. The functional parts of Haskell don't really have anything for me, at least not to compensate the pain of not getting anything done.

Take lens, for instance. It's an incredibly complicated solution to a problem that AFAIK only plagues Haskell! I'd love to know of any exceptions.

Writing networking code was an exercise in frustration where I had to try multiple libraries and faff about with changing types from eager to lazy bytestrings..

I'm glad I bothered to try and learn Haskell. I just don't see me ever using it in production, let alone try to hire anyone who knows it. It's hard enough finding Python programmers who know what generator expressions are.

Re: Dependent Haskell

#85
post #49

Earlier quoted context omitted.

> Haskell is simple That it might be, but it sure as hell isn't easy. Brainfuck is simple, but nobody would choose to write a real project in it. Most programmers struggle trying to understand what a monad is. That's not easy. The free monad is not easy. Monad transformers are not easy. Understanding foldable/traversable/arrows/applicate is not east. Lens is/are not easy. I have personally worked with dozens of progr…

> Brainfuck is simple, but nobody would choose to write a real project in it. Sure. But it's worth knowing whether a language is simple or not (and what tradeoffs have been made to get there). > Most programmers struggle trying to understand what a monad is. That's not easy. It's easier than achieving Haskell-like defect rates in languages that have ad-hoc built in solutions to the same problems, IME. > The free mona…

> It's easier than achieving Haskell-like defect rates in languages that have ad-hoc built in solutions to the same problems, IME.

My first Haskell program type-checked and passed all tests. It was incredibly broken. As in it didn't work at all. I understood monads and it didn't help one jot.

Monads in other languages _can_ be helpful. It pays off to know what one is. But in Haskell, more often than not they're being used to solve problems other languages don't even have in the first place.

> Disagree. Certainly it's a lot easier than solving the same problem by hand.

How? Anyone knows how to write a test double by hand. Most people can use a mocking framework. The visitor pattern is in the GoF book. These are well known and don't involve completely changing the type signature of the code you're writing just so you can interpret it. And let's not even mention Lisp.

> Agreed, but again, easier than achieving the same defect rates without them.

Not really. Write pure code, test it, have a thin layer of side-effects around it. The transformer stack is solving, again, problems only Haskell has. I don't need the state monad anywhere else, so I don't need to layer it on top of anything. In a language with exceptions, ditto. And so on.

> Easier than understanding dozens of ad-hoc informally specified implementations of half of them, which is what working in an ecosystem without them boils down to.

I would bet good money that in my old team I wouldn't be able to explain what an applicative functor is to 90% of them if I had one month of full time training.

> Perhaps not, but easier than achieving the same defect rate without them.

Solves, yet again, a problem only Haskell has.

Re: Dependent Haskell

#86
post #59

Earlier quoted context omitted.

> Haskell is simple That it might be, but it sure as hell isn't easy. Brainfuck is simple, but nobody would choose to write a real project in it. Most programmers struggle trying to understand what a monad is. That's not easy. The free monad is not easy. Monad transformers are not easy. Understanding foldable/traversable/arrows/applicate is not east. Lens is/are not easy. I have personally worked with dozens of progr…

Wanna name a supposedly easy language and let’s see if we can come up with a list of things about it that are kinda difficult?

And that would prove what, exactly? That no language is perfect we already know. My assertion is that, for the vast majority of programmers, Haskell is fundamentally harder than the languages they already know or could learn instead.

Re: Dependent Haskell

#87

Earlier quoted context omitted.

> Haskell is simple That it might be, but it sure as hell isn't easy. Brainfuck is simple, but nobody would choose to write a real project in it. Most programmers struggle trying to understand what a monad is. That's not easy. The free monad is not easy. Monad transformers are not easy. Understanding foldable/traversable/arrows/applicate is not east. Lens is/are not easy. I have personally worked with dozens of progr…

Comparing Haskell to brainfuck is a little hyperbolic -- you do not have fully understand Monads and their underpinnings to be productive in Haskell. Just like when new programmers write "public static void main" and have no idea what it does, or how JAR files work, or how cout works, newbies can type `do` and get off and running. In Haskell most of your time is spent writing non-monadic code -- writing pure function…

> you do not have fully understand Monads and their underpinnings to be productive in Haskell

I don't think that's true. Most programming is done in a team, and someone will have written a transformer stack. I was told to use the free monad to solve my testing problem in my first Haskell program. "Hello world" doesn't count.

> the difficulty contained within is fundamental to computation itself.

Not always. The examples I gave are all of what I consider to be "unforced errors". I don't need monad transformers in any other language I've written code in. Or lens. Or arrows. Or free monads. Or...

> I'm trying to encourage people to try it at least once to see the difference.

I did. Hence me even knowing what lens is.

> concepts like traversable show up in file/folder walking, graph traversal, all these problems that you might think were not generically solvable if you only ever dealt with libraries that worked at the lower level (as in one library for walking graphs and the other for walking the filesystem).

Honest question: how is knowing Haskell's traversables (which are hard) going to add to one's knowledge if one has already worked with any of the following:

* C++ iterators * Python iterables * D ranges * C++20 ranges * (I think) Clojure's transducers?

Sure, Python and Clojure are less applicable due to being dynamic, but D and C++? Generic. Same goes for foldable.

> As long as these programmers learn the paradigms

They wouldn't be able to. I say this as someone who somehow managed to take a student who didn't know how to add fractions together and tutor him to the point of (just) passing a university Linear Algebra class.

> Maybe it's just me, but I see value in languages that expand the way I think

So do I. Trying to learn Haskell was enlightening. I can't see me picking it as the tool of choice for pretty much any project though.

> software developers/engineers who want to work smarter and not harder.

When I wrote Haskell I found myself working harder, writing bugs anyway and wondering what the point was. It's intellectually interesting, and worth looking into. I just don't want to write in it.

Re: Dependent Haskell

#88
post #49

Earlier quoted context omitted.

> Brainfuck is simple, but nobody would choose to write a real project in it. Sure. But it's worth knowing whether a language is simple or not (and what tradeoffs have been made to get there). > Most programmers struggle trying to understand what a monad is. That's not easy. It's easier than achieving Haskell-like defect rates in languages that have ad-hoc built in solutions to the same problems, IME. > The free mona…

> It's easier than achieving Haskell-like defect rates in languages that have ad-hoc built in solutions to the same problems, IME. My first Haskell program type-checked and passed all tests. It was incredibly broken. As in it didn't work at all. I understood monads and it didn't help one jot. Monads in other languages _can_ be helpful. It pays off to know what one is. But in Haskell, more often than not they're being…

> Monads in other languages _can_ be helpful. It pays off to know what one is. But in Haskell, more often than not they're being used to solve problems other languages don't even have in the first place.

Every language faces the same problems; your only options are to not solve the problem at all, solve it in an ad-hoc way, or solve it with a general feature.

E.g. every language faces the problem that error handling can be quite boilerplatey. Bad languages don't solve this at all. Somewhat better languages offer an ad-hoc language feature like exceptions, which are superficially nice (indeed superficially nicer than monadic error handling). But every ad-hoc language feature is one more thing to keep in mind when working or debugging, so they all come at a penalty to your defect rate: exceptions lead to "magic" control flow which can lead to resources not getting closed on error paths, seemingly-innocuous refactors changing behavior, and so on.

> Anyone knows how to write a test double by hand. Most people can use a mocking framework.

Until you ask them to test code that relies on something async, and then they'll write flaky tests, or no tests at all. And I don't think I've ever seen a decent test double for something like a database (most people give up and use an in-memory one). Even those who write tests tend to end up with tests that are much more boilerplatey than main code and not kept up to date, because mocking frameworks rely on magic reflection that means you can't refactor code that uses them the normal way.

> Write pure code, test it, have a thin layer of side-effects around it.

And when the business logic you're implementing is inherently coupled to effectful questions and effect actions, what then? Distort your code, invent some ad-hoc datastructure to represent a half-complete business decision that needs to rely on the answer from some other service?

> I don't need the state monad anywhere else, so I don't need to layer it on top of anything. In a language with exceptions, ditto. And so on.

Well, you need state, you need error-handling; either you do these things manually and directly (painfully verbose and unmaintainable, leading to high defect rates), you do them in a "magical" unmanaged way (high defect rates because you can no longer know what code interferes with what other code), or you manage them explicitly, at which point you need a way to interleave managed effects.

> I would bet good money that in my old team I wouldn't be able to explain what an applicative functor is to 90% of them if I had one month of full time training.

Bet you could. I simply don't believe that anyone who can understand the "visitor pattern" or "observables" or "factories" or whatever the OO pattern of the week is could struggle with applicative functors. It's an interface consisting of two functions of at most two arguments. It's really not that hard.

> Solves, yet again, a problem only Haskell has.

Not so; every substantial system I've seen has ended up needing some way to pass a "patch" or "change" around between different bits of code. The only choice is whether you do it in an ad-hoc way or a standard one.

Re: Dependent Haskell

#89
post #3

I really do think Haskell is a wonderful tool, but: "Haskell, at its core, is simple: it is just a polymorphic lambda calculus with lazy evaluation plus algebraic data types and type classes." In a different context, I would have interpreted that as a sarcastic parody of Haskell evangelists. Really, I feel like everyone who is going to read that article will either already know that, or will have no idea what that se…

What that quote means is that you can take a Haskell program and compile it into lambda calculus and this is what GHC is more or less doing. This has important implications. From a theoretical perspective, it's easier to prove that the language remains sound when you add new features. But also from a more practical point of view, it's easier to work on compiler backends for a more minimal language, to target new CPUs…

The choir already understands all that. You lost everyone else at the words "lambda calculus".

Go into a random PHP shop, and I would be surprised if a single person would know what lambda calculus is.

I'm not complaining about the message, I'm complaining about the language you are using. If you want to evangelize for Haskell, you need to use words that someone who failed out of differential calculus will recognize and understand.

Re: Dependent Haskell

#90

Earlier quoted context omitted.

Easy for whom? Finding Haskell difficult is nothing to be ashamed of. However it's going to appear more difficult than it ought to be if you're approaching it as an experienced programmer with strong opinions. It can be humbling to realize that there's a whole branch of programming you're completely new to and know little about. It's going to be difficult to climb that mountain and you will feel like a beginner again…

> Easy for whom? Nearly everyone I have met and/or worked with. > Finding Haskell difficult is nothing to be ashamed of Agreed. > It can be humbling to realize that there's a whole branch of programming you're completely new to and know little about. Agreed. > It's worth the effort! To learn it? Sure. To use it? I disagree. I was more unproductive with Haskell than I've ever been with C, which is usually the language…

If we're only talking experiences here then I can say that I've written plenty of networking code in C. I grew up on C. I have 15+ years' experiencein C-like languages across the gamut; more if you count the years when I was a youth and hacking together games and homework assignments for fun.

I've definitely felt the pain you're describing and have even thought of lens in the way you ascribe. How can anyone be productive in a language where logging is so difficult to add? I can add logging to a Python application in 3 lines. And as you say... converting from lazy to strict from text to bytestring to string depending on the library. So annoying! Nothing like those clean examples they show you in the tutorials!

Every time I went down that rabbit hole was because I was getting frustrated with feeling like a beginner again. What was I getting from Haskell for all of this hassle? Why were these simple things in other languages so hard? What's the benefit?

Peace of mind.

It's easier to get started with a C or Python or Javascript program. Partly because of experience. Partly because those languages do nothing to isolate side effects, constrain mutation, or check my code in any effective way. I stick to a particular style (usually functional), I write tests first, and I usually end up paying for that easy start later on in the project when, despite our intentions and efforts; side effects, mutation, and plain old type errors creep in. What I gain in efficiency early on in the project I pay for later with interest. The interest rate is only compounded when we start adding team members.

My experience with Haskell has been that it is frustrating and sometimes slower to get started with, especially when I was first starting out, but that it has been worth the effort in the long run. Down the road when my project started to grow I was better equipped to manage the complexity because I had a type system that kept me honest and guided me towards strong designs. I had a tool that would ensure that only the parts I was really sure about could perform IO actions or use shared mutable state. And best of all I could not touch a module for months and when I came back to it there's a good chance I could understand what it was doing, make the change I needed to make, refactor it, and push it to production without any worries.

I think the human side of software development was the nicest feature of working with Haskell. As I added new team members I didn't have to worry about junior developers breaking the build as much. Training was much more straight forward. The documentation was much easier to write as we could focus on the higher-level designs and let the type system document the details. Testing was more effective as we could focus on problems and tests that brought more value to the business problems.

I still choose other languages for various reasons but Haskell has been worth it in my experience. Painful but worth it.

Post reply on HN