Live data from Hacker News

Failing in Haskell

jappie.me

31–40 of 55 posts

Re: Failing in Haskell

#31
post #3

> If we need to compose these errors in a larger program we can simply wrap previous errors in a bigger sumtype This approach is being adopted in GHC itself to compose errors happening at different stages of the compilation pipeline: each stage has its own error type which later becomes a branch of the global error type. Another interesting post about errors-as-values in Haskell is "The Trouble with Typed Errors": ht…

> https://www.parsonsmatt.org/2018/11/03/trouble_with_typed_er...

Nice. I've asked for a way to do that in the past and never found a good answer, in any language! It's not exactly conventional Haskell though, is it? What I really want is first-class support in the language - something like checked and unchecked exceptions in Java, except that if a method declaration lacks a `throws` keyword then all the checked exceptions are inferred by the compiler. For example, the compiler might add `throws A, B, C` to a method that lacks a `throws` keyword. Now if you want to assert that a certain method throws a certain exception, you could write `throws A, *` which means "If this method does not throw an exception of type A, I want a compiler error. If this method throws additional exception types, infer them as usual." Omitting the asterisk (eg `throws A`) would disable the inference and thus would work like a normal `throws` in real Java. You should also be able to assert that a certain exception type is not thrown, for example `throws * except F, G` or something like that.

Re: Failing in Haskell

#32
post #26
post #5

I've written small stuff in Haskell a decade ago. I have a soft spot for the language -- it has clearly influenced many notable languages that came after it. But I also admire the patience of anyone who actually manages to use it in practice, there are so many little papercuts that don't get resolved, basically for a decade or more. If I'm cynical, I'd say that's because little practical stuff is often not worth publ…

Partial functions and exceptions are a compromise solution for the fact that you sometimes do know more than the compiler does. I think it's fine to throw an exception in the case of "programmer error". It's the equivalent of assertions in other languages. Yes, it can blow up, but at least the error is a bit more localised. Having head return a Maybe means that you'll have to awkwardly handly a Nothing case even in s…

Haskell has had non-empty lists as a type for a long time: https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-...

Having partial functions in the Prelude is, as far as I know, widely regarded as a mistake and they are only kept around for backwards compatibility. Anyone writing code nowadays should be using safeHead or non-empty lists.

Re: Failing in Haskell

#33
post #20

Adressing the whitespread conception "It is hard to programm in Haskell because it is pure": If you can write python, you can write Haskell. Don't believe me? 1. Write your program completely in the IO Monad, in a huge do-block 2. Factor out as much pure functionality as possible (= Have as little code in your big IO-programm as possible.) Start at 1. and iterate 2. as many times as you please. It will already be a p…

I like the idea of iterating from imperative to functional. Here the devils advocate for your if you can do it in python you can do it in haskell: I use quite a bit of numpy, scipy and matplotlib, are there equivalent libraries for Haskell?

Re: Failing in Haskell

#34
post #20

Adressing the whitespread conception "It is hard to programm in Haskell because it is pure": If you can write python, you can write Haskell. Don't believe me? 1. Write your program completely in the IO Monad, in a huge do-block 2. Factor out as much pure functionality as possible (= Have as little code in your big IO-programm as possible.) Start at 1. and iterate 2. as many times as you please. It will already be a p…

What Haskell did with Monads is nice, but eventually Monads are just tags on what functionality the function uses.

That being said, I like that Nim and Koka did exactly that. You just tag the functions (IO, Async, Whatever) and it works.

In Haskell, you need monad transformers (which have a runtime costs) or whatever else was made to allow you to work with multiple different effects.

Re: Failing in Haskell

#35
> Some of my intelligent colleagues mucked up error handling. Not only were they failing, they were failing WRONG 1. This frustrates me because doing failing correctly in Haskell is quite easy

Leaving aside that publicly shitting on your colleagues is an extremely bad look and makes you come across incredibly arrogant, isn’t the fact that the intelligent colleagues didn’t get it pretty strong evidence that error handling in Haskell in fact isn’t easy?

Re: Failing in Haskell

#36
post #33
post #20

Adressing the whitespread conception "It is hard to programm in Haskell because it is pure": If you can write python, you can write Haskell. Don't believe me? 1. Write your program completely in the IO Monad, in a huge do-block 2. Factor out as much pure functionality as possible (= Have as little code in your big IO-programm as possible.) Start at 1. and iterate 2. as many times as you please. It will already be a p…

I like the idea of iterating from imperative to functional. Here the devils advocate for your if you can do it in python you can do it in haskell: I use quite a bit of numpy, scipy and matplotlib, are there equivalent libraries for Haskell?

Well... wasn't numpy, at least initially, a Python wrapper around Fortran libraries? Sure, that made them accessible to a bunch more people, but it wasn't some Python-only wonder. Someone could probably write the same bindings for Haskell, if they haven't already.

Re: Failing in Haskell

#37
post #30

Earlier quoted context omitted.

The issue as I see it, is that one of the main selling points of a pure language like Haskell, is that you have to explicitly state where a certain class of surprises/failures (from IO) lie, and therefore, you can account for them better, handle them cleanly, prevent them from arising accidentally or in some ways maliciously, etc. Partial functions are another kind of surprise/failure, but they are not at all explici…

IO is not (primarily) about where failures lie, but about where side effects lie- side effects are where you start caring about the order of execution. Array indexing failures, on the other hand, are not something you typically care about at quite that granularity- they're usually just bugs, not something to recover from except perhaps at a much higher level. The parent comment lumps these kinds of failures in with n…

You make a good point about IO, I forgot how it's also not great about errors (but isn't there are an IO monad with better error treatment? -- it has been several years...). I also agree about granularity and tedium, but that's orthogonal to whether exceptions are the best way to approach such errors, and I don't think they are. Even Go's approach of explicit if-return is not tedium to me, but there are even less tedious approaches, that still let you handle the handle-able errors and do some last-ditch cleanup or just panic on the unhandle-able ones like indexing errors.

The interesting thing about Haskell exceptions are the async ones and the ability to `throwTo`, but I never really had a use for that, so on the whole, that was a bit of an encumbrance too. It's like trying to write exception safe C++ -- tedious and easy to get wrong. I remember a fair few sections of Parallel and Concurrent Programming in Haskell that temporarily didn't handle exceptions correctly, and it often wasn't for pure pedagogical reasons. Great book though.

Re: Failing in Haskell

#38
post #33

Earlier quoted context omitted.

I like the idea of iterating from imperative to functional. Here the devils advocate for your if you can do it in python you can do it in haskell: I use quite a bit of numpy, scipy and matplotlib, are there equivalent libraries for Haskell?

Well... wasn't numpy, at least initially, a Python wrapper around Fortran libraries? Sure, that made them accessible to a bunch more people, but it wasn't some Python-only wonder. Someone could probably write the same bindings for Haskell, if they haven't already.

Maybe some of the experts could name the haskell equivalent libraries/wrappers.

Re: Failing in Haskell

#39

> Some of my intelligent colleagues mucked up error handling. Not only were they failing, they were failing WRONG 1. This frustrates me because doing failing correctly in Haskell is quite easy Leaving aside that publicly shitting on your colleagues is an extremely bad look and makes you come across incredibly arrogant, isn’t the fact that the intelligent colleagues didn’t get it pretty strong evidence that error hand…

This isn't isolated to Haskell. Bad errors are everywhere. And by some of my colleagues, I mean YOU TOO!

Re: Failing in Haskell

#40
post #26

Earlier quoted context omitted.

Partial functions and exceptions are a compromise solution for the fact that you sometimes do know more than the compiler does. I think it's fine to throw an exception in the case of "programmer error". It's the equivalent of assertions in other languages. Yes, it can blow up, but at least the error is a bit more localised. Having head return a Maybe means that you'll have to awkwardly handly a Nothing case even in s…

Haskell has had non-empty lists as a type for a long time: https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-... Having partial functions in the Prelude is, as far as I know, widely regarded as a mistake and they are only kept around for backwards compatibility. Anyone writing code nowadays should be using safeHead or non-empty lists.

Or pattern matching that takes account of the empty list case. Orrrrr using a fold! I usually find when I start matching on list values that the function could be better expressed with a fold instead.
Post reply on HN