10 ms·
Flix – Next-generation reliable, concise, functional-first programming language
- TylerE 6y agoThis seems to just about single-handly take my least favorite syntax feature from each of of the languages it cribs from... FS path based import, overly verbose types with too much &{}% noise, "let" noise, oh and it runs on JVM. Edit: I'm not quite as negative as I sound, but given the headline (or the CTA on the homepage for that matter), I am much less than whelmed. This seems fine I guess, but just another "check all the boxes" language that doesn't really bring much of anything obvious new to the table.
- herbstein 6y ago> This seems fine I guess, but just another "check all the boxes" language that doesn't really bring much of anything obvious new to the table. Full disclosure: I have contributed a small amount of code to the standard library of Flix. Personally I find the inclusion of Datalog as a first-class citizen in an otherwise functional language to be a pretty powerful feature that I personally haven't really seen done before.
- tw25513397 6y ago> Personally I find the inclusion of Datalog as a first-class citizen in an otherwise functional language to be a pretty powerful feature that I personally haven't really seen done before. It's neat, but IIUC, it needing to be a language feature (versus being included as a library) emerges from the lack of macro support. That's one of my issues with non-macro languages, I have to wait for the language owners to add this stuff.
- jorkadeen 6y agoIn Flix, Datalog constraints are first-class values. This is strictly more powerful than a macro system. For example, the Datalog programs that are constructed can depend on input values to the program. This is not the case for macros which are expanded compile-time. (Unless you have some kind of reflection in mind...) EDIT: I hope to explore a macro system for Flix in the future. So we are definitely on the same side of the issue; just wanted to point out that the current system is more powerful.
- fanf2 6y agoHow does Flix compare to Mercury? https://mercurylang.org/ https://mercurylang.org/
- deleted 6y ago[deleted]
- pie_flavor 6y agoYou may want to check the language guide. / is just the namespace separator, it's not a file finder. Could just as easily have been made :: instead.
- jorkadeen 6y ago> This seems fine I guess, but just another "check all the boxes" language that doesn't really bring much of anything obvious new to the table. Flix aims to occupy a unique point in the design space. It combines features from programming languages like Go, Haskell, OCaml, and Scala in a way that no other language does. It has: - a sound type system (like Haskell and OCaml) - a complete local type inference algorithm (like Haskell and OCaml) - eager evaluation (like OCaml and Scala) - CSP style concurrency (like Go) - type classes (like Haskell) - full tail call elimination (like OCaml and Haskell) If you look at the "Innovations" page you will find that Flix has (at least) two features found in no other programming language: a polymorphic type and effect system and first-class Datalog constraints. (I am one of the authors of Flix).
- the-smug-one 6y agoRacket has delimited continuations (from which you can build effects w/o the types) and Datalog as a #lang. Sure, not a lot of types unless you use Typed Racket, that's true. I also don't see why you couldn't swap out Datalog with another constraint system, like that described in Monadic Constraints (Wadler, Stuckey, Sch-something). I think the effect system is cool. How does Flix differ from Eff or Unison in this matter?
- jorkadeen 6y agoThe Datalog implementation in Racket is neat, but does not support stratified negation nor are the Datalog constraint first-class. Both features make it significantly more practical to work with Datalog. Also, the Flix type system ensures - at compile-time - that all first-class Datalog values constructed at run-time are stratified. The effect system in Flix is focused on a single effect: purity. It is very fine-grained (compared to e.g. systems based on rows) and it supports effect inference and effect polymorphism. Eff and Unison have richer effect systems - based on algebraic effects - which allow re-interpretation of effects. However these effects system struggle more with effect inference. For example, I believe that in Eff you only have a restricted form of effect polymorphism / the use of higher-order functions is more limited. (I am one of the authors of Flix)
- xupybd 6y agoAt first I was not sure what this language is trying to achieve. If I understand correctly the sentence below sums it up. "Flix can be thought of as a meta-programming language for Datalog."
- dunefox 6y ago"Alternatively, Flix can be thought of as a functional programming language with a very powerful embedded query language. A Flix programmer can use first-class Datalog constraints to simply, elegantly, and efficiently solve fixpoint computations inside functional code. It should be noted that Datalog is strictly more expressive than relational algebra (~= simple SQL)."
- xupybd 6y agoI've been wanting to try and build a toy solver for the guillotine problem. https://en.m.wikipedia.org/wiki/Guillotine_problem#:~:text=The%20guillotine%20problem%20is%20a%20problem%20in%20combinatorial%20geometry%20and%20in%20printing.&text=The%20Guillotine%20problem%20is%20important,lines%20to%20obtain%20smaller%20panels https://en.m.wikipedia.org/wiki/Guillotine_problem#:~:text=T.... This language looks like a perfect fit.
- divs1210 6y agoHow does it achieve full tail call elimination and csp while compiling to java bytecode?
- tw25513397 6y agoPure speculation on my part (since I couldn't find any details either): their "Closed world assumption" and "No reflection" principles [1] could mean the compiler can output radically different bytecode, e.g., eliminating the tail call by eliminating the "call" altogether. That said, I might be wrong given that the FAQ [2] notes that tail call elimination "has some run-time performance cost"; maybe they're baking in a trampoline. [1] https://flix.dev/principles/ https://flix.dev/principles/ [2] https://flix.dev/faq/ https://flix.dev/faq/
- jorkadeen 6y agoAt the moment it uses a technique called "Impure Functional Objects" - which are a form of reusable stack frames. In the future we may switch to trampolines and eventually if Project Loom succeeds we will try to use whatever infrastructure they come up with. (I am one of the authors of Flix)
- divs1210 6y agointeresting, thanks!
- coldtea 6y agoDon't trampolines allow TCO in any language?
- rixed 6y ago> unboxed primitives I'm wondering how this is achieved given the type system and garbage collector. What types are unboxed and when?
- jorkadeen 6y agoFor example: Given the type List[Int] the cons cells of each list contain a primitive integer and a pointer to the next cons cell. (In Java, you would instead have List[Integer] where each element of the list is a boxed/wrapped Integer object). I hope that answers your question? (I am one of the authors of Flix).
- rixed 6y agoUnboxed integers is no big feat. Many implementations of garbage collected languages have unboxed small scalars (OCaml and Guile come to mind). What about compound types?
- tw25513397 6y agoReading through the Design Principles [1]: > Separate pure and impure code So IIUC, the effect system [2] means impurity is contagious. This seems reasonable to me, though I wonder what that means in practice. `Console.printLine` is impure [3], and presumably any debug logging would be too; the contagion might spread pretty far. I wonder if this is why seemingly pure functions like `Array.find` are flagged as impure [4]. > Principle of least surprise: ... and when there is no immediately obvious default, we should not have a default at all, but force the programmer to be explicit about his or her intention. I like that they called this part out. I'd wager most code really doesn't have sane defaults, just the defaults that made sense to the developer at the time. > Local type inference I find that in languages with type signatures (without inference), folks lean on the type to convey information, and in dynamic languages like Clojure, folks lean on good naming. Based on my not-much experience with type inference, the code ends up with neither. Sure the compiler can figure out what it is, but the humans not so much. > Uniform function call syntax: ... the function call length(xs) can also be written as xs.length() I wonder what their motivation was for this; my guess is to appeal to both FP and OO devs. IMO, having multiple ways of writing the same thing is likely to lead to unnecessary style wars. > Private by default: ... declarations are hidden by default (i.e. private) and cannot be accessed from outside of their namespace I like this a lot, though I foresee running into issues with unit testing, and thereby arguments over at what level things should be tested. > Bugs are not recoverable errors: ... For recoverable errors, we should enforce that they are checked and handled. For program bugs, we should terminate execution as quickly as possible This seems reasonable to me, but I'm curious what counts as a "program bug", or how to know that some error is recoverable. > No null value Meh. I've think Option is just null with extra steps. NPEs arise because of method invocation, e.g., `x.foo()` while `x` is null. In FP languages like Clojure, NPEs don't really happen since `x` is just a value being passed to a function. With nil-punning and reasonable behavior of core functions (e.g., `(get m k)` yields nil when `m` is nil), an unexpected nil is really a type error. > No dead or unreachable code / No unused variables Perhaps it's from my REPL-driven, exploratory style of development, but I think having to constantly comment out code I'm ambivalent about just to get it to compile would be a bit annoying. I'd think something like this should be a compile option, but I think that runs afoul of their "One Language"/"no flags" principle. > No variadic (varargs) functions Having worked with enough Clojure, and seen enough bugs when using `apply` on vararg fns, I think this is a good choice. IIUC, their approach would replace, e.g., `(+ x y z ...)` with `(sum [x y z ...])`. > No binary or octal literals: ... It is our understanding that these features are rarely used in practice. Until you need to do some bit-twiddling; maybe they still have hex. I wonder what they considered the downside of including it. [1] https://flix.dev/principles/ https://flix.dev/principles/ [2] https://flix.dev/innovations/ https://flix.dev/innovations/ [3] https://api.flix.dev/Console https://api.flix.dev/Console [4] https://api.flix.dev/Array https://api.flix.dev/Array
- Razengan 6y agoThe first thing I check every time a new language claims to be "modern" and "next generation": Whether or not it has mandatory semicolons. So far so good! :)
- stewbrew 6y agoThis actually looks like a language I would like to use. Datalog like constraints were surprising. The current state of JVM interoperability makes it clear though this is a research project. Could this be ported to other "hosting" languages/VMs? In any case, I think interoperability with foreign code needs a different solution and it has to have a way to fully deal with OOP constructs.
- garganzol 6y agoSame for me, Flix looks like a language I would use professionally. It has that powerful OCaml/F# vibe. Built-in Datalog is indeed a surprising feature. Strongly reminded me that we may come to a universal data model someday just like we rely on universal computational model (Turing / von Neumann) nowadays. Under that model, we would not make distinctions between various sources of data and we would be able to efficiently query them in every structural dimension they offer.
- xvilka 6y agoAt least OCaml and Haskell compile into the native code, thus faster by definition.
- tw25513397 6y agoWhile it may be faster, the "by definition" part hasn't been true for years. The JVM can do some amazing stuff at runtime to outpace statically executed code. Regardless, their principles [1] make the trade-offs clear: - Developer productivity over runtime performance - Correctness over performance [1] https://flix.dev/principles/ https://flix.dev/principles/
- jorkadeen 6y agoI don't think that is true. For example, Java beats OCaml on some benchmarks at: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/ocaml-java.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... It seems that the situation is not as clear cut as your post suggests. (I am one of the authors of Flix)
- johnnycerberus 6y agoHas anyone tried runnig those benchmarks with AOT Java? Microbenchmarks like these tell absolutely nothing about general performance because they are short-lived. JVM is a beautiful piece of engineering and I believe you guys chose well this platform to host it, always hoped for a ML-inspired language running on the JVM and this looks like it.
- igouy 6y ago> Has anyone tried runnig those benchmarks with AOT Java? Yes. GraalVM CE 20.0.0 and native-image. > …because they are short-lived. https://benchmarksgame-team.pages.debian.net/benchmarksgame/sometimes-people-just-make-up-stuff.html#jvm-startup-time https://benchmarksgame-team.pages.debian.net/benchmarksgame/... Because "general performance" is ill-defined. Because tiny tiny programs aren't like other programs.
- 6y ago
- neolog 6y agoWhat's the intended use case? Is it supposed to be "a better F#, for the JVM"?
- thomasfl 6y agoI am waiting for someone to name their programming language yafpl - yet another functional programming language.
- jorkadeen 6y agoI think your comment is covered in the FAQ: https://flix.dev/faq/ https://flix.dev/faq/ > Can we just stop building new programming languages? We build new programming languages and we do research on programming languages because we want to offer developers better tools to write programs. We want tools that make it simpler, safer, and faster to write correct programs. We want tools that increase productivity and that aid in program maintenance. The situation is not unlike why we would want better airplanes, better houses, or better surgical instruments. (I am one of the authors of Flix)
- xupybd 6y agoCan you elaborate on this? >We are planning to define division by zero as yielding zero Is there a non mathematical reason for that choice?
- jorkadeen 6y agoThe alternatives are: - Division must be impure (because it can throw an exception, crash the program, etc.) - Division must be partial - i.e. return Option[Int]. Both seem worse compared to defining division by zero as zero. Coq, Lean, and Pony do the same. https://github.com/ponylang/pony-tutorial/blob/master/content/gotchas/divide-by-zero.md https://github.com/ponylang/pony-tutorial/blob/master/conten...
- idclip 6y agoRepackaged scala? How is this different?
- the-smug-one 6y agoEffects, discerning pure/impure funcs (through effects, AFAIK), better type inference, sound type system, no null, no exceptions. Honestly, just for the language I'd pick Flix over Scala.
- jorkadeen 6y agoAdding to that: effect inference and polymorphism, unboxed primitives, full tail call elimination, extensible records, first-class Datalog constraints, CSP style concurrency, a multitude of different design choices. (I am one of the authors of Flix)
- coldtea 6y agoIn that it's a totally different language? FP and JVM doesn't mean Scala.
- esarbe 6y agoIt looks and feels very much like Scala, in my opinion. That's not a bad thing at all.
- willtim 6y agoIt's great to see structural typing in the form of polymorphic extensible records. But I am a bit disappointed they didn't go further, I would have at least liked to see extensible variants. The tuple-based syntax, also makes it rather noisy to use anonymous records as arguments (e.g. for named parameters). If I was designing a new modern language, I would make the default types structural records and variants and use a single "new type" form for creating nominal types, when necessary. Compositional datatypes are much easier to achieve with structural records/variants (e.g. define a new enum set based on another). It is also trivial to make a structural type nominal, but not to go the other way. But having structural records as something special alongside nominal ADTs (like Flix, Elm and Purescript), does not exploit the duality and does not give a modern rethink that IMHO is needed.
- Barraketh 6y agoCould you elaborate on the "compositional datatypes"? What is the use case?
- willtim 6y agoBy "compositional datatypes", I mean being able to define datatypes and functions on them in a modular fashion. I gave a very simple example with enums. For a real world use case, imagine a compiler pipeline, where we have an AST that we are desugaring over multiple steps. Ideally we want a succession of ASTs that remove the form being eliminated, so the AST type can guarantee it's eliminated. This is very easy with structural variants, there's no need to actually define and name each separate AST, which differs only slightly. Or imagine we are typing a SQL join that is a merge of two existing record types. Such "compositional data types" can be achieved with elaborate encodings and type-level computations in a language like Haskell (see e.g. Data types `a la carte), but it's difficult and somewhat ugly. There is an opportunity here for improvement.
- siraben 6y agoYou can do this with the tagless-final encoding, which has a similar flavor to Data types à la carte's concept of open data types. As an example, define class ExpSYM a where add :: a Int → a Int → a Int lit :: Int → a Int class MulSYM a where mul :: a Int → a Int → a Int Now suppose we extend with booleans and so on. We can freely combine addition and multiplication. As we add new data variants, old code need not be recompiled. We get the openness of OOP's class extensions with the flexibility of ADTs. ex1 :: (ExpSYM a, MulSYM a) => a Int ex1 = add (lit 3) (mul (lit 4) (lit 5)) Not enough space here but you can also pattern match over final terms and interpret them in different ways (e.g. CBN vs CBV interpreters). Then as you go through your compiler pass you can see through the types that "capabilities" get reduced more and more until you reach some base language (sounds like free monads doesn't it?). Tangentially if I were to design an FP language I would use tagless final for everything, and deforest as much as I can (if possible) to reduce overhead. How this affects other aspects (e.g. automatically translating pattern matching) I have not looked into, but it's interesting nonetheless.
- tleb_ 6y agoWhy does this website require JavaScript? It won't render anything without it.
- retrofuturism 6y agoThen whitelist it. Jesus.
- coldtea 6y agoIt requires JS because they designed it this way. Is a thread discussing the language the place to solve/change this?
- uryga 6y ago@jorkadeen since you're here: the landing page's two-column layout doesn't work great on mobile, you get two columns that are like 2-words wide: Recent | Bread- News | and Butter | Functional 2020-11-20 | Programming We are on | Twitter! Find | Flix supports us at | basic building @flixlang. | blocks of typed | functional programs (Android, recent Firefox) it'd probably be good to switch the divs to `class="col-xs-12 col-md-6"` or equivalent
- deleted 6y ago[deleted]
- jorkadeen 6y agoThanks- I will try to get it fixed!
- siraben 6y agoI'm curious about the emphasis on fixpoints and lattices. These are two quite simple concepts often overlooked in CS and emphasized even less in programming languages. Lattices are natural to CS in that any time you have an order or even any binary relation, that imposes some structure on your values, and knowing the/solving for unique fixpoints (considering also continuity conditions) can be powerful, for instance the most general type of an expression, the "final" result of a recursive definition, infinite streams, final states of an imperative program and so on. Seems to me that Flix would further blur the line between logic and functional programming (using what looks like some Prolog-esque search and datalog integration), amazing!
- adenozine 6y agoThis is the worst syntax I've seen in a functional language, by far. Semicolons, braces, symbolic soup, et al. It's like if Scala, Java and Haskell had a one night stand in the center of Chernobyl.
- twoquestions 6y agoI don't mind the punctuation noise, but I might just have bad taste. I'm stealing the "had a one night stand in the middle of Chernobyl", that's hilarious!
- deleted 6y ago[deleted]
- rafaelvasco 6y agoI liked it. Clean to my eyes. Worst syntax for me are Lispy languages followed by Rust. That is punctuation hell;