[HN Gopher] Flix - A powerful effect-oriented programming language
___________________________________________________________________
Flix - A powerful effect-oriented programming language
Author : freilanzer
Score : 192 points
Date : 2025-07-10 14:02 UTC (8 hours ago)
(HTM) web link (flix.dev)
(TXT) w3m dump (flix.dev)
| voat wrote:
| I'd love to use Flix for something. It looks beautiful. But I'm a
| web dev, and never touch the JVM ecosystem
| Joker_vD wrote:
| Oh, but you can just transpile it to WASM using e.g. TeaVM [0].
| Just add another build step to your bundler or whatever web dev
| uses nowadays to build apps.
|
| [0] https://github.com/konsoletyper/teavm
| phplovesong wrote:
| JVM is a no-starter. The language looks nice tho, shame they
| built it on JVM.
| atemerev wrote:
| I don't know, Kotlin, Scala and Clojure are quite successful.
| latexr wrote:
| I don't think they mean the JVM makes it a non-stater in
| general, but a non-starter _for them_.
| jorkadeen wrote:
| The JVM is a state-of-the-art virtual machine with multiple
| open source implementations, a large ecosystem, and a fast JIT
| compiler that runs on most platforms. It is hard to find
| another VM with the same feature set and robust tooling.
| withinboredom wrote:
| Yes... with a million weird environment variables that can
| affect your runtime.
| foxygen wrote:
| So don't change them? Parent comment still applies to stock
| JVM.
| Joker_vD wrote:
| Which is amazing, you can fine tune the performance of the
| runtime to your heart's content. Or you can just leave them
| as-is, the default behaviour is quite reasonable too.
| eikenberry wrote:
| I think the problem is that it targets a VM instead of native
| machine architectures, not the quality of the VM. I also find
| the times I need to target a VM to be very limited as I'm
| generally writing code for a specific platform, not a cross
| platform application. Of course this will vary between
| developers.
| cmrdporcupine wrote:
| Targeting JVM means not having to roll your own garbage
| collector.
|
| And bonus, you get a huge world of third party libraries
| you can work with.
|
| It's been over a decade since I worked on the JVM, and Java
| is not my favourite language, but I don't get some people's
| hate on this topic. It strikes me as immature and "vibe"
| based rather than founded in genuine analysis around
| engineering needs.
|
| The JVM gets you a JIT and GC with almost 30 years of
| engineering and fine tuning behind it and millions of eyes
| on it for bugs or performance issues.
| jorkadeen wrote:
| I strongly agree. Java and JVM bytecode may not be our
| "cup of tea", but it is simply unrealistic to implement
| any runtime environment with comparable performance,
| security, robustness, and tooling. The only alternative
| is WASM, but they are not yet there feature-wise.
| eikenberry wrote:
| The JVM is a large and complex system with tons of
| configurable options. If you don't need it, why add all
| that cognitive overhead when you have perfectly good
| options that don't. And the benefits you gain are very
| limited if you aren't integrating with other JVM based
| systems.
| dontlaugh wrote:
| The practical problems are slow startup time and high
| minimum memory usage. Since those are encountered early
| on in the developer experience, the reaction many have is
| predictable.
| esafak wrote:
| Don't say you'd pick the PHP JIT!
| withinboredom wrote:
| It has an actual IR now... so theoretically it's actually
| possible...
| satvikpendem wrote:
| I'd use HipHopVM like Facebook instead
| pshirshov wrote:
| Graal Native Image and you have your native binary.
| artemonster wrote:
| HN: "not written in Rust or LISP, pass"
| phkahler wrote:
| >> Flix is a principled effect-oriented functional, imperative,
| and logic programming language...
|
| >> Why Effects? Effect systems represent the next major evolution
| in statically typed programming languages. By explicitly modeling
| side effects, effect-oriented programming enforces modularity and
| helps program reasoning.
|
| Since when do side effects and functional programming go
| together?
| noelwelsh wrote:
| FP isn't _really_ about eliminating side effects. Controlled
| effects are fine. That 's what an effect system does.
|
| Avoiding side effects is really just a side effect (pun
| intended) of older programming language technology that didn't
| provide any other way to control effects.
| tossandthrow wrote:
| Arguably FP _really_ is about eliminating side effects.
|
| The research has sprung out of lambda calculus where a
| computation is defined in terms of _functions_ (remember:
| _Functional_ programming).
|
| Side effects can only be realized by exposing them in the
| runtime / std-lib etc. How one does that is a value
| judgement, but if a term is not idempotent, then you arguably
| does not have a functional programming language anymore.
| hocuspocus wrote:
| Effect systems in FP languages give you precisely that:
| referential transparency.
| tome wrote:
| Funny you mention that because that's exactly how my talk
| at ZuriHac 2025 started, video published just yesterday:
|
| https://www.youtube.com/watch?v=RsTuy1jXQ6Y
| noelwelsh wrote:
| You gotta ask the question: why does FP care about
| eliminating side effects? There are two possible answers:
|
| 1. It's just something weird that FP people like to do; or
|
| 2. It's in service of a larger goal, the ability to reason
| about programs.
|
| If you take the reasonable answer---number 2---then the
| conclusion is that effects are not a problem so long as you
| can still reason about programs containing them. Linear /
| affine types (like Rust's borrow checker) and effect
| systems are different ways to accommodate effects into a
| language and still retain some ability to reason about
| programs.
|
| No practical program can be written without effects, so
| they must be in a language somewhere.
|
| More here: https://noelwelsh.com/posts/what-and-why-fp/
| astrobe_ wrote:
| > No practical program can be written without effects, so
| they must be in a language somewhere.
|
| Or rather, very few. It is like programming languages
| that trade Turing-completeness for provability, but
| worse.
|
| In theory, one could imagine a program that adds 2
| matrices in a purely functional manner, and you would
| have to skip on outputting the result to stay side-
| effect-free. Yet, it is running on a computer so the
| program does affect its internal state, notably the RAM
| in which the result is visible somewhere. One could dump
| that memory from outside of the program/process itself to
| get the result of the computation. That would be quite
| weird, but on the other hand sometimes normal programs do
| something like that by communicating through shared
| memory.
|
| It seems that the notion of side effects must be
| understood relatively to a predefined system, just like
| in physics. One wouldn't count heat dissipation or power
| consumption as a side effect of such a program, although
| side-channel-attackers have a word to say about this.
|
| (from your link:) > Both languages allow mutation but
| it's up to us to use it appropriately.
|
| This is the crux of the problem. If you add a C example
| to your Typescript and Scala examples, people will throw
| you stones for that statement - out of instinct. The
| intent is to prevent accidental misuse. Mutation is
| "considered harmful" by some because it can be
| accidentally misused
| noelwelsh wrote:
| > It seems that the notion of side effects must be
| understood relatively to a predefined system, just like
| in physics. One wouldn't count heat dissipation or power
| consumption as a side effect of such a program, although
| side-channel-attackers have a word to say about this.
|
| Absolutely! When you really dig into it, the concept of
| an effect is quite ill-defined. It comes down to whatever
| some observer considers important. For example, from the
| point of view of substitution quick sort and bubble sort
| are equivalent but most people would argue that they are
| very much not.
|
| The preface of https://www.proquest.com/openview/32fcc806
| 4e57c82a696956000b... is quite interesting.
| tikhonj wrote:
| If you start with lambda calculus you don't have effects in
| the first place, so there's nothing to eliminate. Lambda
| calculus and friends are perfectly reasonable languages for
| computation in the sense of _calculation_.
|
| A better way to think about general-purpose functional
| programming is that it's a way to _add_ effects to a
| calculation-oriented foundation. The challenge is to keep
| the expressiveness, flexibility and useful properties of
| lambda calculus while extending it to writing interactive,
| optimizable real-world programs.
| sparkie wrote:
| To retain referential transparency, we basically need to
| ensure that a function provided the same arguments always
| returns the same result.
|
| A simple way around this is to never give the same value to
| a function twice - ie, using uniqueness types, which is the
| approach taken by Clean. A uniqueness type, by definition,
| can never be used more than once, so functions which take a
| uniqueness type as an argument are referentially
| transparent.
|
| In Haskell, you never directly _call_ a function with side
| effects - you only ever _bind_ it to `main`.
|
| Functions with (global) side effects return a value of type
| `IO a`, and the behavior of IO is fully encapsulated by the
| monadic operations. instance Monad IO
| where return :: a -> IO a (>>=) ::
| IO a -> (a -> IO b) -> IO b -- aka "bind"
|
| return lifts a pure value into IO, and bind sequences IO
| operations. Importantly, there cannot exist any function of
| type `IO a -> a` which escapes IO, as this would violate
| referential transparency. Since every effect must return
| IO, and the only thing we can do with the IO is bind it,
| the eventual result of running the program must be an IO
| value, hence `main` returns a value of type `IO ()`.
| main :: IO ()
|
| So bind encapsulates side effects, effectively using a
| strategy similar to Clean, where each `IO` is a synonym of
| some `State# RealWorld -> (# State# RealWorld, a #)`. Bind
| takes a value of IO as it's first argument, _consumes_ the
| input `State# RealWorld` value and extracts a value of type
| `a` - feeds this value the next function in the sequence of
| binds, returning a new value of type `IO b`, which has a
| _new_ `State# RealWorld`. Since `bind` enforces a linear
| sequencing of operations, this has the effect that each
| `RealWorld` is basically a unique value never used more
| than once - even though uniqueness types themselves are
| absent from Haskell.
| Sharlin wrote:
| Lisp always had side effects and mutability, and it's the
| canonical FP language, directly inspired by lambda
| calculus. To be fair, before Haskellers figured out monads,
| nobody even knew of any way to make a FP language that's
| both pure and useful.
| jorkadeen wrote:
| In Flix all effects are tracked by the type and effect system.
| Hence programmers can know when a function is pure or impure.
| Moreover, pure functions can be implemented internally using
| mutation and imperative programming. For example, in Flix, one
| can express a sort function that is guaranteed to be pure when
| seen from the outside, but internally uses a quick sort (which
| sorts in place on an array). The type and effect system ensures
| that such mutable memory does not escape its lexical scope,
| hence such a sort function remains observationally pure as seen
| from the outside.
|
| (I am one of the developers of Flix)
| reddit_clone wrote:
| This sounds very nice!
| tikhonj wrote:
| Functional programming a la Haskell has always been about
| making effects controllable, explicit first-class citizens of
| the language. A language entirely without effects would only be
| useful for calculation.
|
| The talk about "purity" and "removing side effects" has always
| been about shock value--sometimes as an intentional marketing
| technique, but most often because it's just so much easier to
| explain. "It's just like 'normal' programming but you can't
| mutate variables" is pithy and memorable; "it's a language
| where effects are explicitly added on top of the core and are
| managed separately" isn't.
| pasquinelli wrote:
| running on a machine is a side effect.
| Jonovono wrote:
| If you are in the JS ecosystem, you should check out Effect TS
| (https://effect.website)
|
| It's a very fun time
| hocuspocus wrote:
| Effect TS is monadic though, as it's a pretty direct re-
| implementation of Scala's ZIO.
| satvikpendem wrote:
| Even though it's called effect, it has almost nothing to do
| with algebraic effects, which is what this language and others
| like OCaml 5 have, and so Effect TS is more like Haskell (as it
| came from fp-ts).
| Joker_vD wrote:
| On a language semantics note: the semantics of
| extending/restricting polymorphic records seem to follow Leijen's
| approach [0] with scoped labels. That is, if you have a record
| e.g. r1 = { color = "yellow" }, you _can_ extend it with r2 = {
| +color = "red" | r1 }, and doing r2#color will evaluate to
| "red"... and if you then strip the field "color" away, r3 = {
| -color | r2 }, then you'll get back an original record, r3#color
| will evaluate to "yellow". Which IMO is the sanest approach, as
| opposed to earlier attempts of trying to outlaw such behaviour,
| preferably statically (yes, people developed astonishingly high-
| kinded type systems to track records' labels, just to make sure
| that two fields with the same label couldn't be re-added to a
| record).
|
| [0] https://www.cs.ioc.ee/tfp-icfp-gpce05/tfp-proc/21num.pdf
| pshirshov wrote:
| Awesome, it even supports HKTs.
|
| Can't find any mentions of typeclasses though, are they
| supported?
|
| Give me typeclasses and macros comparable with Scala ones and I
| would be happy to port my libraries (distage, izumi-reflect, BIO)
| to Flix and consider moving to it from Scala :3
|
| UPD: ah, alright, they call typeclasses traits. What about
| macros?
|
| UPD2: ergh, they don't support nominal inheritance even in the
| most harmless form of Scala traits. Typeclasses are not a
| replacement for interfaces, an extremely important abstraction is
| missing from the language (due to H-M typer perhaps), so a lot of
| useful things are just impossible there (or would look ugly).
| jorkadeen wrote:
| Flix supports type classes (called "traits") with higher-kinded
| types (HKTs) and with associated types and associated effects.
| A Flix trait can provide a default implementation of a
| function, but specific trait instances can override that
| implementation. However, Flix has no inheritance. The upshot is
| that traits are a compile-time construct that is fully
| eliminated through monomorphization. Consequently, traits incur
| no runtime overhead. Even better, the Flix inliner can "see
| through" traits, hence aggressive closure elimination is often
| possible. For example, typical usage of higher-order functions
| or pipelining is reduced to plain loops at the bytecode level
| without any closure allocation or indirection.
|
| Flix does not yet have macros-- and we are afraid to add them
| due to their real (or perceived) (ab)use in other programming
| languages.
|
| We are actively looking for library authors and if you are
| interested, you are more than welcome to stop by our Gitter
| channel.
| exceptione wrote:
| Sorry to hijack, but since you are involved, can you explain
| why tail call optimization would incur a run time perf
| penalty, as the docs mention? I would expect tail call
| optimization to be a job for the compiler, not for the
| runtime.
| helix278 wrote:
| TCO (tail call optimization) is often confused with TCE
| (tail call elimination), the latter is a runtime guarantee
| whereas the former is a compiler's best effort attempt to
| statically optimize tail calls.
| exceptione wrote:
| Thanks! So you are implying that `TCO :: Maybe TCE`?
|
| I am trying to think of a situation where a functional
| language compiler does not have enough information at
| compile time, especially when effects are witnessed by
| types.
| helix278 wrote:
| I'm not a compiler dev, but I know that many functional
| programming languages struggle with this in the same
| manner if the target platform does not support TCE
| itself, and therefore require trampolining.
| jorkadeen wrote:
| We have to emulate tail calls using trampolines. This means
| that in some cases we have to represent stack frames as
| objects on the heap. Fortunately, in the common case where
| a recursive function simply calls itself in tail position,
| we can rewrite the call to a bytecode level loop and there
| is no overhead.
| exceptione wrote:
| Thanks for explaining that term. That sounds really bad
| indeed. Maybe this is way too technical, but representing
| them as stack pointers was unfeasible?
| jorkadeen wrote:
| The JVM (and other VMs for that matter) do not grant
| direct access to the stack.
|
| But the good news is that the common case incurs no
| overhead.
| pshirshov wrote:
| > The upshot is that traits are a compile-time construct that
| is fully eliminated through monomorphization.
|
| So, apparently, I can't re-implement distage for Flix.
|
| I don't mind a little bit of overhead in exchange for a
| massive productivity boost. I don't even need full nominal
| inheritance, just literally one level of interface
| inheritance with dynamic dispatching :(
|
| > their real (or perceived) (ab)use in other programming
| languages.
|
| Without macros I can't re-implement things like logstage
| (effortless structured logging extracting context from AST)
| and izumi-reflect (compile-time refleciton with tiny runtime
| scala typer simulator).
| andoando wrote:
| I like it. This is the first time Ive seen a new programming
| language demo that made me want to use it
| lutzh wrote:
| I looked and Flix a while ago and found it really interesting -
| so much so that I wrote an article "Flix for Java Programmers"
| about it. Might actually be a bit outdated by now.. need to look
| at Flix's recent development again.
|
| But if you're interested:
| https://www.reactivesystems.eu/2022/06/24/flix-for-java-prog...
| jorkadeen wrote:
| Cool blog post! With your permission, I would be happy to add
| it here: https://doc.flix.dev/blog-posts.html
|
| The language has improved a lot in the years since the post. In
| particular, the effect system has been significantly extended,
| Java interoperability is much improved, and some syntax have
| been updated.
| klabb3 wrote:
| Wow what a gold mine your blog is. It's like a more elaborate
| and well thought through version of thoughts that have been
| torturing me for years. Looking forward to reading it all.
| exceptione wrote:
| I am deeply impressed by the depth and breadth of this language.
| Algebraic data types, logic programming, mutability, all there
| from the get go.
|
| Another aspect that I love from their comparison table is that a
| single executable is both the package manager, LSP and the
| compiler. As I understand, the language server for Haskell
| has/had to do a lot of dances and re implement things from ghc as
| a dance between the particular ghc version and your cabal file.
| And maybe stack too, because I don't know which package manager
| is the blessed one these days. Not to shit on Haskell -- it is
| actually a very fine language.
|
| However, the best feature is a bit buried and I wonder why.
|
| _How ergonomic is the integration with the rest of the JVM, from
| the likes of Java?_ AFAIK, types are erased by JVM compilers...
| With the concept of `regions` they have at least first class
| support for imperative interaction. Note: With the JVM you get
| billions worth of code from a high quality professional standard
| library, so that is a huge plus. That is why the JVM and .net
| core are IMHO the most sane choices for 90+% of projects. I think
| the only comparable language would be F#. I would love to see a
| document about Flix limitations in the JVM interoperability
| story.
|
| __EDIT__
|
| - There is a bit of info here. Basically all values from
| Flix/Java have to be boxed/unboxed.
| https://doc.flix.dev/interoperability.html
|
| - Records are first-class citizens.
| littleroot wrote:
| >a single executable is both the package manager, LSP and the
| compiler
|
| oh my i just know you're going to love unison
| exceptione wrote:
| Thanks for giving me homework. :-)
| dontlaugh wrote:
| Indeed. I even like the syntax.
| joe_the_user wrote:
| As a non-functional-programming, c-language-familiar person,
| the syntax look fabulous. It seems like the first functional
| language I've seen that makes simple things look simple and
| clear.
| pshirshov wrote:
| > AFAIK, types are erased by JVM compilers...
|
| Not in all the cases (it keeps type parameters for anonymous
| classes) and there are various workarounds.
|
| Also, essentially, it's not a problem at all for a compiler,
| you are free to render applied type constructors as regular
| classes with mangled names.
| jorkadeen wrote:
| The parent poster is correct. We do monomorphization, hence
| Flix types are unboxed. For example, a `List[Int32]` is a
| list of primitive integers. There is no boxing and no
| overhead. The upshot is that sometimes we are faster than
| Java (which has to do boxing). The downside is larger
| bytecode size-- which is less of a factor these days.
|
| Caveat: Flix sometimes has to box values on the boundary
| between Flix and Java code -- e.g. when calling a Java
| library methods that requires a java.lang.Object due to
| erasure in Java.
| eximius wrote:
| `case Circle(r) => 3 * (r * r)`
|
| I, uh, think your math might need some checking :)
| tomtom1337 wrote:
| Relevant xkcd: https://xkcd.com/2205/
| mcdow wrote:
| Anyone have a good primer on what effect-oriented programming
| looks like and how it's used? Feel free to shill your own blog!
| rendaw wrote:
| It looks like "effect" as in impure functions in a functional
| language? I.e. a new way of dealing with effects (global/hidden
| state mutations) in a language that makes the pure-impure
| distinction. I'm not entirely sure.
|
| I thought it was going to be something like contracts or
| dependent types or something.
| adastra22 wrote:
| No. It is essentially resumable exceptions. You throw an
| exception saying "I need a MyAlgebraicType" and the effect
| handler catches the exception, generates the value, and
| returns execution to the place the exception was called from.
| helix278 wrote:
| But entirely definable in user code, so an effect is
| essentially a set of possibly impure operations you can
| perform (like I/O or exception throwing), and a function
| that exhibits that effect has access to those operations.
| Of course the call sites then also exhibit that effect,
| unless they provide implementations of the effect
| operations.
| ww520 wrote:
| Effect system allows programmers to annotate expressions that
| can have certain effects, just like the type system annotating
| type information on them, so compilers can enforce effect rules
| just like enforcing type rules.
|
| For example for a type system, let a: Int
| // this says 'a' has the type Int a = 5 //
| compiler allows, as both 'a' and 5 are of Int. a = 5.1
| // disallowed, as 'a' and 5.1 are of different types.
|
| Similarly for example for an effect system, let
| a: Int let b: Int!Div0 // 'b' is of type Int and the Div0
| effect. let c: Int ... a = 1 / c //
| disallowed, as '/' causes the Div0 effect which 'a' not
| supported b = 1 / c // allowed, as both '/' and 'b'
| support the Div0 effect.
|
| The effect annotations can be applied to a function just like
| the type annotations. Callers of the function need to
| anticipate (or handle) the effect. E.g. let's say the above
| code is wrapped in a function 'compute1(..) Int!Div0', a caller
| calling it can do. compute1(..) on effect(Div0)
| { // handle the Div0 effect. }
| jlward4th wrote:
| Shilling my book "Effect Oriented Programming"
| https://effectorientedprogramming.com/
|
| The book uses Scala & ZIO but intends to be more about the
| concepts of Effects than the actual implementation. I'd love to
| do a Flix version of the book at some point. But first we are
| working on the TypeScript Effect version.
| jprokay13 wrote:
| What's the best way to stay informed about the typescript
| version?
| jlward4th wrote:
| We are working with the Effect folks and will make some
| noise about it with them. Otherwise, you can follow me on
| X: James Ward
| mcdow wrote:
| Small world! Searched 'effect oriented programming' and one
| of your talks was one of the first results on YouTube.
|
| https://youtu.be/EHtVADr-x94
| naasking wrote:
| // Computes the delivery date for each component. let r =
| query p select (c, d) from ReadyDate(c; d)
|
| _facepalm_. Select should always come last, not first, haven 't
| we learned anything from the problems of SQL? LINQ got this
| right, so it should look like: query p from
| ReadyDate(c; d) select (c, d)
|
| Very cool language otherwise.
| IshKebab wrote:
| Yeah PRQL also got this right and it's sooo much nicer.
| jorkadeen wrote:
| It is a fair point-- the implicit argument being that this
| allows `c` and `d` to be bound before they are used, and hence
| auto-complete can assist in the `select` clause. Nevertheless,
| the counter argument is that the form of a logic rule is:
| Path(x, z) :- Path(x, y), Edge(y, z).
|
| i.e. an implication from right to left. This structure matches:
| query p select (x, z) from Path(x, y), Edge(y, z).
|
| So the trilemma is:
|
| A. Keep the logic rules and `query` construct consistent (i.e.
| read from right-to-left).
|
| B. Reverse the logic rules and query construct-- thus breaking
| with decades of tradition established by Datalog and Prolog.
|
| C. Keep the logic rules from right-to-left, but reverse the
| order of `query` making it from left-to-right.
|
| We decided on (A), but maybe we should revisit at some point.
| naasking wrote:
| I appreciate the desire for consistency and being able to
| lean on old textbooks and documentation. A couple of
| considerations since this is a new language where history and
| precedent should (I think) be less important if it leads to
| clarity and improved productivity:
|
| 1. I think way more people coming to your language will be
| familiar with SQL and it's problems than with logic
| programming and Horn clauses.
|
| 2. I think many people are now familiar with functional
| pipelines, where filters and transforms can be applied in
| stages, thanks to the rise of functional programming in
| things like LINQ and Java's Stream API. This sort of
| pipelining maps naturally to queries, as LINQ has shown, and
| even to logic programming, as uKanren has shown.
|
| 3. People don't type programs right-to-left but left-to-
| right. To the extent that right-to-left expressions interfere
| with assisting the human that's typing in various ways (like
| autocomplete), I would personally defer to helping the human
| as much as possible over historical precedent.
|
| 4. Keeping the logic fragment separate from the query
| fragment (option C) seems viable if you really, really want
| to maintain that historical precedent for some reason.
|
| My two cents. Kudos on the neat language!
| pmontra wrote:
| Probably Elixir spoiled me but when I see enum
| Shape { case Circle(Int32), case Square(Int32),
| case Rectangle(Int32, Int32) } def area(s: Shape):
| Int32 = match s { case Circle(r) => 3 * (r * r)
| case Square(w) => w * w case Rectangle(h, w) => h *
| w }
|
| I wonder why not this syntax: def area(s:
| Shape.Circle(r)) = { 3 * (r * r) } def area(s:
| Share.Square(w)) = { w * w } def area(s: Shape.Rectangle(h,
| w)) = { h * w } area(Shape.Rectangle(2, 4))
|
| The Int32 or Int32, Int32 types are in the definition of Shape,
| so we can be DRY and spare us the chances to mismatch the types.
| We can also do without match/case, reuse the syntax of function
| definition and enumerate the matches in there. I think that it's
| called structural pattern matching.
| akkad33 wrote:
| > can also do without match/case, reuse the syntax of function
| definition and enumerate the matches in there. I
|
| I think that is multi-methods
| ddellacosta wrote:
| > The Int32 or Int32, Int32 types are in the definition of
| Shape, so we can be DRY and spare us the chances to mismatch
| the types
|
| I have to admit I don't see the distinction here in terms of
| DRYness--they are basically equivalent--or why the latter would
| somehow lead to mismatching the types--presumably if Flix has a
| typechecker this would be a non-issue.
|
| I use Elixir now at work and I have used Haskell and PureScript
| personally and professionally, which both support analogs of
| both the case syntax and function-level pattern matching, and
| in my experience the case syntax is often the better choice
| even given the option to pattern match at the function level.
| Not that I'd complain about having both options in Flix, which
| would still be cool, but I don't think it's as big of a benefit
| as it may seem, especially when type checking is involved.
| pmontra wrote:
| Because I might write enum Shape {
| case Circle(Int32), def area(s: Shape): In32 =
| match s {
|
| Not only I had to write something that the compiler already
| knows, but I typed a compilation error. The second type
| definition is there only to make developers write it wrong.
| It does not add any information.
| akkad33 wrote:
| What if you make a typo and instead of `area` you type
| `areas` the second time? I also don't see how one is more
| DRY than the other. If anything in the second example you
| typed `Shape` and `area` a bunch of times, so to me it's
| less DRY
| ddellacosta wrote:
| > The second type definition is there only to make
| developers write it wrong.
|
| Int32 is the type of the return value for the function
| (https://doc.flix.dev/functions.html), which is distinct
| information not implied by the type being passed in
| (Shape), so I dispute this characterization--the fact that
| this type is the same type as the parameter given to all of
| Shape's terms is specific to this example. Furthermore I
| suspect it would immediately be caught by the typechecker
| regardless.
|
| While in a language like Haskell you could define this
| function without a type definition and its type would be
| inferred (vs. in Flix, see https://doc.flix.dev/functions.h
| tml?highlight=inference#func...), regardless I will almost
| always declare the type of top-level functions (or even
| non-top-level functions) for clarity when reading the code.
| I think this is useful and important information in any
| case.
| textlapse wrote:
| Tangential, but I have a basic question: What makes Aarhus
| (mainly its university/techhub) a powerhouse for Programming
| Languages?
|
| C++, C#/Typescript, Dart, etc all have strong roots in that one
| small area in Denmark.
|
| In general, I am curious what makes some of these places very
| special (Delft, INRIA, etc)?
|
| They aren't your 'typical' Ivy League/Oxbridge univ+techhubs.
|
| Is it the water? Or something else? :)
| wslh wrote:
| Lineage? Aarhus has a strong academic tradition in areas like
| logic, type theory, functional programming, and object oriented
| languages. Many influential researchers in these fields have
| come through there.
|
| I also think there's a noticeable bias toward the US in how
| programming language research is perceived globally.
| Institutions like Aarhus often don't invest heavily in
| marketing or self-promotion, they just focus on doing solid
| work. It's not necessarily better or worse, but it does make it
| harder for their contributions to break through the layers of
| global attention.
| mollerhoj wrote:
| Our long winters + free education sure doesn't hurt either -
| what better way to spend the yearly 6 months of darkness than
| working on a new proglang?
| bodzioney wrote:
| Yes exactly. Aarhus had Martin-Lof, Nygaard, etc. Similarly,
| INRIA has had many influential researchers as well as OCaml
| and Rocq. Talent (and exciting projects) attracts more
| talent. But that doesn't mean it doesn't exist in US. Penn,
| Cornell, CMU, MIT and others have had historically very
| strong PL faculty. My understanding is due to the nature of
| grants in US it doesn't give faculty the same freedom to work
| on what they choose as in Europe. So you get different
| research focuses because of that.
| syhol wrote:
| Very similar to the koka language. I hope these effect systems
| become mainstream.
| miniBill wrote:
| Very cool language. The standard library looks mostly sane,
| although it does have `def get(i: Int32, a: Array[a, r]): a \ r`
| which means that it must have some kind of runtime exception
| system. Not my cup of tea, but an understandable tradeoff
___________________________________________________________________
(page generated 2025-07-10 23:00 UTC)