Live data from Hacker News

Grain: A strongly-typed functional programming language for the modern web

grain-lang.org

101–110 of 156 posts

Re: Grain: A strongly-typed functional programming language for the modern web

#101

Pretty much the first sentence on the page: > No runtime exceptions, ever. Every bit of Grain you write is thoroughly sifted for type errors, with no need for any type annotations. That's... weird to me. That seems to posit that ALL runtime exceptions are necessarily type errors. Huh? What about full disk, DB errors, data verification error, parsing errors, network errors, and tons of other errors that don't appear t…

Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore. A harder problem is errors that cannot be handled by a simpler type system. For example, consider Haskell's head function, which is defined like this: head :: [a] -> a In other words, it takes a list, and returns the first…

You still can't avoid runtime errors because of non-terminating functions. Determining whether an arbitrary function in a Turing complete language is total or not is undecidable. I don't see any mention of a totality checker (which would make the language not Turing complete) either. Idris also has this.

Re: Grain: A strongly-typed functional programming language for the modern web

#102

Pretty much the first sentence on the page: > No runtime exceptions, ever. Every bit of Grain you write is thoroughly sifted for type errors, with no need for any type annotations. That's... weird to me. That seems to posit that ALL runtime exceptions are necessarily type errors. Huh? What about full disk, DB errors, data verification error, parsing errors, network errors, and tons of other errors that don't appear t…

Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore. A harder problem is errors that cannot be handled by a simpler type system. For example, consider Haskell's head function, which is defined like this: head :: [a] -> a In other words, it takes a list, and returns the first…

> This can be solved by dependent typing

dependant typing isn't needed for some use cases you have mentioned:

> list must not be empty you can use NonEmpty

https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-L... . We are still encoding this special case and our intent in types. Cons is that we need a special support for it (special library) where with dependant types we could reason about this use case without a special library

EDIT: added newlines

Re: Grain: A strongly-typed functional programming language for the modern web

#104

Pretty much the first sentence on the page: > No runtime exceptions, ever. Every bit of Grain you write is thoroughly sifted for type errors, with no need for any type annotations. That's... weird to me. That seems to posit that ALL runtime exceptions are necessarily type errors. Huh? What about full disk, DB errors, data verification error, parsing errors, network errors, and tons of other errors that don't appear t…

Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore. A harder problem is errors that cannot be handled by a simpler type system. For example, consider Haskell's head function, which is defined like this: head :: [a] -> a In other words, it takes a list, and returns the first…

> Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore.

Mostly because Go is terrible.

> Haskell's type system is extremely powerful, but it cannot catch this at compile time.

The problem is not the type system, it's that Haskell's error handling is inconsistent.

Elm, despite having a much simpler type system than Haskell, handles this properly:

    head : List a -> Maybe a
This has nothing to do with the type system itself and everything to do with how the type system is used (or not used). The designers of Haskell's `head` decided to make it a partial function, leading to type-checking inputs not generating any output.

Re: Grain: A strongly-typed functional programming language for the modern web

#105

Pretty much the first sentence on the page: > No runtime exceptions, ever. Every bit of Grain you write is thoroughly sifted for type errors, with no need for any type annotations. That's... weird to me. That seems to posit that ALL runtime exceptions are necessarily type errors. Huh? What about full disk, DB errors, data verification error, parsing errors, network errors, and tons of other errors that don't appear t…

I would assume case B, which isn't really that unique. Erlang for example follows that pattern (and has no concept of "exception"). After all, I/O errors, parsing errors, etc., aren't exceptional; they very much should be expected. Forcing them to be handled in the normal code path helps create robust systems. (There are of course also true runtime errors -- e.g. out-of-memory -- and precondition errors -- i.e., codi…

> Erlang for example follows that pattern (and has no concept of "exception").

Erlang absolutely has a concept of exceptions. They're even called exceptions: http://erlang.org/doc/reference_manual/errors.html#exception....

Re: Grain: A strongly-typed functional programming language for the modern web

#107

Earlier quoted context omitted.

Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore. A harder problem is errors that cannot be handled by a simpler type system. For example, consider Haskell's head function, which is defined like this: head :: [a] -> a In other words, it takes a list, and returns the first…

> Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore. Mostly because Go is terrible. > Haskell's type system is extremely powerful, but it cannot catch this at compile time. The problem is not the type system, it's that Haskell's error handling is inconsistent. Elm, despite…

This seems like such an obvious solution it makes me wonder why creators of Haskell did not think of it? Lists are a very basic type used all the time if you don't get that right lot of the value of the great type-system is lost I would think.

Re: Grain: A strongly-typed functional programming language for the modern web

#108
post #35

Earlier quoted context omitted.

Poking around in the sources, it looks like this is the OCaml compiler, with the frontend apparently tweaked to accept the new syntax. But this is not mentioned anywhere that I can see. The "Copyright copyright 2017-2018 Philip Blair and Oscar Spencer." line in the README is highly misleading in this context, since most of the actual source files are marked with OCaml's copyright header.

Many files are taken from the OCaml compiler and then adapted, but changes seems a bit deeper than just a different syntax. It would indeed seem fair for the authors to at least make it clear in the toplevel README that the front-end (parsetree representation and type-checking) is indeed / started as a fork of the OCaml code base. Considering ongoing efforts to create a WebAssembly backend for OCaml (and thus Reason)…

> Many files are taken from the OCaml compiler and then adapted [...]

I went back and checked, and Grain not only takes OCaml's code without clear attribution but redistributes that code under GPLv3 where the original code is under LGPLv2.1. That's bad.

Re: Grain: A strongly-typed functional programming language for the modern web

#109

The main page doesn't do a great job of showing what's interesting about Grain vs. JavaScript. The only hint is this: "No runtime exceptions, ever. Every bit of Grain you write is thoroughly sifted for type errors, with no need for any type annotations." Maybe show some examples of errors Grain would catch that JavaScript wouldn't, like Elm does: http://elm-lang.org/

> No runtime exceptions, ever. This is something I wonder about JS: there are a lot of places that exceptions happen in (say) Python that just return `NaN` or `undefined` in javascript. Is it intentional? Is it a good idea? Examples: the multiplication operator essentially never throws. Out-of-bounds (or "not found") lookups don't throw. I suspect the logic is "only throw if you have the wrong type for that operation…

I think JavaScript simply got it quite wrong by trying to be way too clever. In theory it is fine to say that dividing by 0 is Infinity but what can you do with Infinity?

In practice that causes the output of your program be either Infinity or NaN but the problem is that is usually never what you want.

Then you want to know "Why do I get a NaN here?" and you will have to study all of your program and single step its execution to understand why you got an answer you din't want which is of little value to anybody.

Problem with Infinity is you can not come back from there. It does not cancel out if you subtract it.

Instead IN PRACTICE it is much better to catch errors early with the help of the type-system, unit-tests, and assertions.

It is an interesting challenge: How do I define the type "Any number except zero" and have my type-system then catch divisions by zero?

Re: Grain: A strongly-typed functional programming language for the modern web

#110

Earlier quoted context omitted.

> Errors could presumably be provided as return values (similar to Rust's Option or Haskell's Either), though we know from languages like Go that propagating these manually is a chore and an eyesore. Mostly because Go is terrible. > Haskell's type system is extremely powerful, but it cannot catch this at compile time. The problem is not the type system, it's that Haskell's error handling is inconsistent. Elm, despite…

This seems like such an obvious solution it makes me wonder why creators of Haskell did not think of it? Lists are a very basic type used all the time if you don't get that right lot of the value of the great type-system is lost I would think.

I think it's because they weren't very clear on how they wanted to handle partial functions / error reporting, and historically functions like head are partial.

Making them total makes them a bit heavier for the best case, and furthermore can seem unnecessary (as you could just pattern-match the list itself).

You can also see this oddity in Haskell allowing non-exhaustive case, and allowing refutable patterns in bindings.

Post reply on HN