Strong Arrows for Elixir Gradual Typing

Поділитися
Вставка
  • Опубліковано 25 чер 2024
  • There's ongoing research to add types to Elixir. The idea is to bring gradual typing, but with that come some potential issues. Elixir has a new approach to gradual typing called "strong arrows".
    For more videos like this, check out ElixirStreams.com
    For more on strong arrows, check out the blog post describing it elixir-lang.org/blog/2023/09/...
  • Наука та технологія

КОМЕНТАРІ • 13

  • @germanvelasco
    @germanvelasco  8 місяців тому +1

    A couple of people have asked, shouldn't `debug/1` return `binary()`?
    I think I made that part a bit confusing (live and learn! 😬). Maybe this helps? 👇
    In reality `debug` + `identity` (with the `is_number` guard clause) should fail at compile time. So, `debug` shouldn't ever return `number()` and be correct (since it returns a binary).
    The question we're trying to answer is: What should the type system infer when we don't have a type signature?
    Without the `is_number` guard clause, the `debug` function works well with binaries. But at compile time, a regular type system (without strong arrows) doesn't know what to assign as `debug`'s return type.
    Should it be `dynamic()` or `number()`? There are trade-offs to those options.
    But once we add the `is_number` guard clause to `identity`, then the compiler can correctly say that `number()` (not `dynamic()`) would be the return type. But, of course, because of the binary operation `` in `debug`, it should actually return `binary()`.
    So, the compiler should give us an error at that point.

  • @hank9th
    @hank9th 8 місяців тому +1

    The way I was able to wrap my head around this was to think of "strong arrows" as the combination of the new type system, and existing Elixir checks (e.g. guards or pattern matching).
    This is to address the situation where you have an application that does not have any static type definitions, and you are using a library that didn't used to have static typing, but adds it later.
    You wouldn't want the new internal static typing of that library to suddenly cause your app to fail at compile time, even though the code technically works at runtime.
    Conversely, if your application had a bug in it where it passing an invalid value to a function from this library that had a guard clause, which would eventually cause a runtime error in your system, that library introducing static types would alert you to that bug in compile time. That means the static type system would help you catch an existing bug in your app before it causes problems in production.

  • @mcspud
    @mcspud 7 місяців тому

    Long term Haskell and Ocaml user here, and Typescript of course.
    I think one of the benefits of the Haskell type system is that the syntax has become somewhat ubiquitous, and I think changing it for a different style max cause some fumbling.

    • @germanvelasco
      @germanvelasco  7 місяців тому +1

      That's interesting. I wonder if it'll be a problem or maybe just something for those who're more versed with Haskell/Ocaml/Elm/etc. I like that syntax, but don't mind what Elixir is bringing.
      I think a lot of Elixirists actually expect the typespec syntax. So, it might also cause confusion from that direction, but maybe not. Guess we'll have to wait and see if types do make it to Elixir.

    • @mcspud
      @mcspud 7 місяців тому

      @@germanvelasco well reasoned answer. Without the risk of this turning into bike shedding, I'd wager its almost impossible to keep them out. I saw what happened with Python3 as it went from argument annotations to what is becoming (essentialyl) a full Hindley Milner system.
      I'd argue that this progression is inevitable, and I don't think the typespec syntax will be able to encapsulate what users will eventually demand. (boom, just hit bikeshedding).
      In other news I purchased your "testing liveview" course. As a new Elixir/Phoenix user its been great - cheers.

  • @io2_
    @io2_ 8 місяців тому +1

    @German Velasco long time listener, first time commenter.
    Love your videos and shorts on Elixir & LiveView 👏🏽
    Slight confusion on this one though -
    The operator only works with binary arguments.
    “We got:” 42
    Will throw an ArgumentError
    And even if that weren’t the case, surely your debug function here ALWAYS returns a binary.
    What am I missing?

    • @germanvelasco
      @germanvelasco  8 місяців тому

      Thanks for the kind words! Glad to hear you like the videos. 🥳
      You're totally correct that only works with binary arguments. And you're right that the `debug` function always returns a binary (when evaluated at runtime).
      I was trying to showcase that if we had typed the `identity` function as returning a `number()` (regardless of what it returns in the runtime), and we leave `debug` function untyped, then either the compiler would have to assign `dynamic()` as `debug`'s return type or assign `number()` (which as you point out is confusing because we know it only works with binaries).
      So, strong arrows are a way to try to reconcile that compile time vs runtime discrepancy.
      Does that make more sense? It's kind of a confusing topic, so it might not. José also does a great job of walking through in more detail in the blog post, so that's also worth a look.

    • @germanvelasco
      @germanvelasco  8 місяців тому

      I just rewatched my video, and I think I know what you mean.
      I think the part that I didn't make clear was that `debug` + `identity` (with the `is_number` guard clause) should fail at compile time.
      Without the `is_number` guard clause, the `debug` function works well with binaries. But at compile time, a regular type system (without strong arrows) doesn't know what to assign as `debug`'s return type. Should it be `dynamic()` or `number()`? There are trade-offs to each of those options.
      But once we add the `is_number` guard clause to `identity`, then the compiler can correctly say that `number()` (not `dynamic()`) would be the return type, but of course, because of the binary operation `` in `debug`, it should actually return `binary()`. So, the compiler should give us an error at that point.
      Not sure if I made it even more confusing, but I think I get what you're saying now. Thanks for leaving that comment! Wish I would've explained that better in the video.

  • @AdolfoNeto
    @AdolfoNeto 8 місяців тому +1

    Hi, German! Great work. I am still at 3:12 and i didn't get it. How does debug/1 returns a number()? Shouldn't it return string()? I haven't read the paper yet.

    • @germanvelasco
      @germanvelasco  8 місяців тому +1

      Yeah, I think I made that part a bit confusing (live and learn! 😬). Maybe this helps? 👇
      In reality `debug` + `identity` (with the `is_number` guard clause) should fail at compile time. So, `debug` shouldn't ever return `number()` and be correct (since it returns a binary).
      The question is about what the type system should infer when we don't have a type signature.
      Without the `is_number` guard clause, the `debug` function works well with binaries. But at compile time, a regular type system (without strong arrows) doesn't know what to assign as `debug`'s return type.
      Should it be `dynamic()` or `number()`? There are trade-offs to those options.
      But once we add the `is_number` guard clause to `identity`, then the compiler can correctly say that `number()` (not `dynamic()`) would be the return type. But, of course, because of the binary operation `` in `debug`, it should actually return `binary()`.
      So, the compiler should give us an error at that point.

    • @AdolfoNeto
      @AdolfoNeto 8 місяців тому

      @@germanvelasco Thanks!

  • @BukovTervicz
    @BukovTervicz 8 місяців тому +1

    I'm so confused

    • @germanvelasco
      @germanvelasco  8 місяців тому

      I think I confused a few people with this one😬(check the pinned comment for an attempt at clarifying). Or feel free to just ignore it! If types do come in to Elixir, I think we'll have plenty of time to understand strong arrows. Sorry if I made things more confusing!