10 ms·
I agree with the points in your post and I also want a mainstream typed FP (something with a clear happy path so I don’t need to guess about what prelude or str
by weberc2 8y ago
I agree with the points in your post and I also want a mainstream typed FP (something with a clear happy path so I don’t need to guess about what prelude or string types or standard library or etc to use). The biggest impediment I see is that these language communities are more concerned about the abstract mathematical properties of the language and things like tooling get neglected.
I would love to see a typed FP equivalent to Go—everything is super simple/small learning curve (I should be able to meaningfully contribute to a project after a day or so), the standard library is decent, package management just works, no guessing about what test lib to use, everything compiles to a single static binary by default (dead simple deployments), no-fuss documentation generation, great concurrency/parallelism story, straightforward profiling and optimizations (e.g., if my program is slow because I’m allocating too much in the hot path I can trivially preallocate), etc. These are the things that matter for real world projects—mathematically elegant type systems really are just gravy, which is why Go has been able to be so successful in spite of its flat-footed type system.^1
^1: if you go over to r/programming, no one can figure this out because everyone believes you can’t ship Software in a language without monads or generics, so Go’s popularity must be due to Google marketing.
- akavel 8y agoPersonally, I see Elm as an interesting development in such a direction, i.e. humane FP language, with the author relentlessly striving for simplicity and ease of use kin my opinion, successfully). That said, it's currently limited to a web dev./"frontend" domain (JS replacement).
- vram22 8y ago>Personally, I see Elm as an interesting development in such a direction, i.e. humane FP language, with the author relentlessly striving for simplicity Red is another language that is or was striving for simplicity (or resisting the complexity that seems to be the norm in tech nowadays). In fact that was supposed to be one of its main goals. I felt sad when they went down the ICO route for funding, though. Not sure how FP-ish Red is, though. Rebol, which Red is based on, is supposed to be homoiconic. I like Rebol and Red. The size of the Rebol and Red interpeters (and Red is a compiler too) and the size of the Red EXEs are quite small, which is another plus. Much smaller than some other languages.
- vram22 8y ago>or resisting the complexity I should say, sometimes seemingly unnecessary complexity.
- gtycomb 8y ago> The biggest impediment I see is that these language communities are more concerned about the abstract mathematical properties of the language and things like tooling get neglected Is it really so. I am only asking. A mathematical model allows deeper insight on structure (backed by hundreds of years of prior mathematical thought), and we then sugar it appropriately for users. Just like civil engineers who learn Strength of Materials etc mathematically before they design the bridges we drive over daily. Tooling is one of my gripes also. There was a time decades ago when I couldn't go beyond compiling the simple hello world example. This has gotten much better after many years. Same with Haskell. Is this due to difficulties in getting the necessary financial support.
- bunderbunder 8y agoAt least in the case of Haskell, it is explicitly so. Haskell is a language that is meant to support programming language research, and you can see that manifest itself all up and down the design of its toolchain. It's a woefully under-appreciated factor in Haskell's famous learning curve. OCaml less so, but the Jane Street monoculture means that, if it's not itchy for a trading firm, it's not gotta get scratched. Trading's an odd industry, tech-wise. There are aspects of the OCaml ecosystem that eliminate any of my own desire to use the language that I would have seen as neutral or even strongly positive when I worked at a trading firm. (At least during working hours.) So, yeah, I do think that one of the big things that's missing from typed FP right now is a strong language that has similar semantics to an ML or (preferably) Haskell, but with a much more pragmatic focus. F# is really nice if .NET is an option for you, but I'd sure like to see something that is statically compiled and can produce C-friendly binaries, so that it can play nice with a wider variety of pre-existing codebases.
- rwmj 8y agoThis isn't really true for OCaml. I daily compile large OCaml programs which are linked to C programs, we run valgrind on them, they are fully integrated with GCC and autotools and so on, ship in tarballs to end users who can run ‘./configure && make’ etc. In case that all sounds very Unix-specific, I have also in the past cross-compiled OCaml programs on Linux and Windows and Mac OS X at the same time.
- weberc2 8y agoI wouldn't consider a home-grown autotools/gcc/valgrind setup to be "simple", especially when it comes to dependency management (assuming you care that dependencies don't conflict and that your code links against the right version of the dependency and deterministic/reproducible builds and so on). If you can afford the personnel to manage all of that, then that's great, but for those of us who can't, it's nice to be able to run `go build` or `go test` with zero configuration.
- rwmj 8y agoWhy would you think OCaml can't do that as well? opam lets you build from source with "zero configuration". We don't use it because we have invested heavily in autotools and want to integrate with many other programming languages, but the option is there.
- weberc2 8y agoI'm a little hazy on the particulars because I never got terribly deep into OCaml and haven't tried it in a while, but IIRC, OPAM is a package manager (and according to https://opam.ocaml.org/doc/Packaging.html https://opam.ocaml.org/doc/Packaging.html, it requires a configuration file). The most popular build system for OCaml is JBuild (or whatever it got renamed to) which also requires a configuration file (formatted as S-expressions to make things more confusing for newcomers) and I think that usually bottoms out in a Makefile to boot (or maybe it's the other way around, and OPAM packages usually call into Make which calls into JBuild?). In any case, it's a far cry from `go build`.
- mirekrusin 8y agoCrystal is very close to your list.
- christophilus 8y agoCrystal is interesting-- I've followed it at a distance-- but from what I understand, it's not really functional. Persistent data structures aren't a first-class citizen, and it seems to prefer blocks to lambdas. Also, (unrelated to the functional thing), the compiler isn't super fast. I think a really fast edit -> save -> compile -> reload time is one of the defining features of OCaml and Go.
- kbp 8y ago> it seems to prefer blocks to lambdas What does this mean?
- christophilus 8y agoCrystal prefers these constructs [0] `foo.map {|x| x + 1}` where the stuff between the squiggles is called a "block". I come from Ruby, so maybe Crystal got this one right, but Ruby blocks, at least, are a more limited, less general-purpose approach to lambdas (by which I mean anonymous, first-class functions + closures) [1]. [0] https://crystal-lang.org/docs/syntax_and_semantics/blocks_and_procs.html https://crystal-lang.org/docs/syntax_and_semantics/blocks_an... [1] https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
- mirekrusin 8y agoCrystal has lambdas w/closures (called Proc) with `->{ 1 }` syntax [0]. Because of ruby-like syntax where `foo` is a call if `foo` is a function you need to do `foo.call` on those lambdas explicitly - so you can distinguish between passing them around as values `foo` and calling them `foo.call` or `foo.call(arg1, arg2, ...)`. I've played with it a bit, haven't seen problems with compile times, they were actually pretty good. The nice thing about Crystal is that it is extremely easy to use, terse code, easy macros, fast executables, algebraic types, good packaging story - in general very good ergonomy. I hope it'll pick up one day. [0] https://crystal-lang.org/docs/syntax_and_semantics/literals/proc.html https://crystal-lang.org/docs/syntax_and_semantics/literals/...
- christophilus 8y agoMan, I agree 100%. I wonder if it would be possible to get this by compiling an Elm/SML-like language to Go? [Edit: I'd add a few things to your feature list: really fast, OCaml-speed compilation, along with a utop-like REPL]
- weberc2 8y ago+1 regarding your additions to my list! With respect to compiling an SML-like language to Go (I've thought about this a lot), it would probably get you a long way, but the performance would suffer because FP langs allocate like crazy and Go's GC is not optimized for lots of fine-grained allocations. And there would still be a long tail of things that didn't work quite right: stack traces would need to be modified to map to lines in your source program (instead of the emitted Go code), documentation generation and linking would need to be patched, dependency fetching would need to understand and distinguish between packages in $MYLANG and Go packages (so it invokes the $MYLANG->Go compiler appropriately), and so on. That said, it would certainly be a great proof of concept!
- vram22 8y ago>Go's GC is not optimized for lots of fine-grained allocations Why is it not? Hadn't heard of this point before. Is it because of catering to the most common use cases, which are not fine-grained, maybe?
- weberc2 8y agoGo has value types and they're used pervasively. Where an OCaml or Python or Haskell list is O(n) allocations, a Go slice is 1 allocation (values are laid out side-by-side in memory). This allows Go to have a simple, concurrent GC with pause times on the order of 1us (compared to 10-100ms, as is common for compacting generational collectors) as well as great (CPU) cache properties (things are more likely to be collocated in memory, so you're more likely to have cache hits).
- vram22 8y ago
- deleted 8y ago[deleted]
- _hardwaregeek 8y agoI'd say Rust is the closest thing. Cargo is fantastic, super ergonomic and with an excellent package ecosystem. Rust doesn't have the pretense of purity or immutability, but honestly, you can very easily write pure functional Rust (and it'll save you a lot of pain with lifetimes). Performance is excellent, of course.
- weberc2 8y agoI agree that Rust is the exception--it has a fantastic tooling story, but it's actually the _language_ that holds it back for the sorts of applications I tend to write. The performance and even correctness benefits it affords me over Go are just too small for the cognitive burden it imposes (and yes much of the gap closes with time--I've been kicking the tires on and off for 5 years now--but every year the returns diminish and it's looking like the gap will remain significant). Hopefully I'll be proven wrong in the next few years.
- Ar-Curunir 8y agoWould you mind elaborating on the cognitive burden you find Rust imposes? I find that after roughly two years of writing Rust, I can architect and re-architect big projects fairly clearly, and the type system gives me strong reassurances that refactors haven't screwed things up. Not to mention the advantage of even simple things like enums, which most languages (including Go) tend to lack.
- lolive 8y agoI have heard about Rust. But I wonder if you can do something that a OO programmer (like me :) would call "string subclasses" so you do not manipulate a generic type called string, but a meaningful subclass such as "FirstName" or "LastName", or "TownName".
- steveklabnik 8y agoYou wouldn’t do it as a “subclass”, as Rust doesn’t have classes or inheritance. You’d use the “new type pattern”, which is like a named 1-tuple: struct FirstName(String);
- McWobbleston 8y agoF# touches on most of these points doesn't it?
- weberc2 8y agoLast time I tried using it, it was unclear what build system to use and I had a hard time finding the "happy path" (what test library to use, how to set up my project file to include a test target, etc). It also seems to have this weird FP/OOP dichotomy where some things are methods on a class and others aren't and that affects how you call things and so on. I didn't get far enough to really be able to articulate my problem, but it seems quite complex (albeit much of the complexity probably exists to support interop with other .Net things). I think most of this could be addressed with documentation "How to do X in F#" (I'm sure someone has a writeup somewhere, but I couldn't find any such document around the time I tried it).
- rs86 8y agoFP and OOP are orthogonal... You can have purely functional objects
- phyrex 8y agoI fail to see how this would work. An object is a combination of state and methods acting on the state, and purely functional meaning no state.
- McWobbleston 8y agoF# for fun and profit is an excellent resource
- weberc2 8y agoYeah, I remember trolling through those and I found them really useful and accessible; unfortunately I don't remember the details about why they didn't help me get over the hump (I'm sure if I stuck with it long enough I could have; I just have limited free time).