Scala 3: Match Types | Rock the JVM

Поделиться
HTML-код
  • Опубликовано: 10 сен 2024

Комментарии • 47

  • @rockthejvm
    @rockthejvm  3 года назад +2

    Note: the problem in the video has various solutions which are more or less elegant. The difference between them is subtle, so I totally understand if you disagree with the proposed solution with match types.

    • @anticipayo
      @anticipayo 3 года назад +3

      I like this solution. My only concern is that it doesn't seem extensible. Perhaps extensible match types will be part of scala 3.1?

  • @luismiguelmejiasuarez2020
    @luismiguelmejiasuarez2020 3 года назад +3

    Great video as always!
    Just one thing, I would make a note about the possibility of extending this in a future and relate it with this not being possible in Scala 2. - As already mentioned (even by you) this can be implemented in Scala 2 using a typeclass (with a path-dependant type) + the aux pattern (for better type inference).
    Now, I will not debate the fact that for a small set of types then the match type version is cleaner (and in general I really like them for things like mapping ADTs) but if this is an operation that we would expect to be applied to multiple types and maybe the ones that will provide implementations for those new types will be downstream users, then the match type is just too restrictive and a typeclass becomes a more flexible / general / powerful technique.
    So I believe it is worth to mention that. Which, again, is not to say that match types are always "worse" than typeclasses; I actually find them better for small / contained cases.

  • @martijnriemers
    @martijnriemers 3 года назад +5

    4:37 Couldn’t this be achieved with typeclasses in Scala 2?

    • @rockthejvm
      @rockthejvm  3 года назад

      Not at this clarity - you'd need to wrap everything inside TC instances.

    • @mykytal8991
      @mykytal8991 3 года назад +1

      It may be even better to implement this with typeclasses since with match types all cases are stuffed into one function making addition of new cases problematic when that function comes from a library.

    • @ukaszlampart5316
      @ukaszlampart5316 3 года назад

      @@mykytal8991 It depends, if you are writing a library type-classes are probably a preferable solution, but when you are writing application, match type approach is safer (as far as I am aware if you mess-up pattern match branches you get compile time error) and a lot simpler.

  • @TheNeoanomally
    @TheNeoanomally 3 года назад +1

    Awesome set of videos. Keep up the good work. Your style of explanation is easy, concise and better than reading a blog. Must confess I hate that’s scala3 mix and matches indentation and brackets. I have to work in python 30% of the time and it’s the thing I dislike most stylistically of the language..

    • @rockthejvm
      @rockthejvm  3 года назад +1

      Glad you like the videos. As for Scala 3, just keep the old style, it will work just as fine.

  • @Lumintorious
    @Lumintorious 3 года назад +4

    This was some great coverage. Awesome video. Yours is one of the few channels that make me drop everything to watch whenever you post something.
    As a side question: Do you think the lastComponentOf method would work better as a transparent inline method (return type being transparent at compile time based on an inlined match statemend therefore no match type needed) or do you think the match type would be a better way since it also provides some form of direct documentation?

    • @rockthejvm
      @rockthejvm  3 года назад

      Wow, such high praise, thank you!
      Yes, I think match types are the best solution for this kind of problem. Sure, you can use inlining or other code expansion tools to get to the same result, but nothing comes close to the cleanliness of this one as far as I'm aware.

  • @thajafsal
    @thajafsal 3 года назад +1

    Wow wow! What a nice explanation!

  • @fliprabbit
    @fliprabbit 3 года назад +2

    you're an absolute legend, thank you so much for all these quality videos!!

    • @rockthejvm
      @rockthejvm  3 года назад +1

      Glad they're useful! More incoming!

  • @Nebulorum
    @Nebulorum 3 года назад +2

    Nice video, but still need to explore more the usage. It seems it would help me in a Scala 2 project where I wanted to tie the type of a Question with the Type of the answer. There was no way to express this in types. Could be nice also for functions that translate between different ADT.

  • @sergeydev8273
    @sergeydev8273 3 года назад +1

    Thanks guys for the great lectures!:)

    • @rockthejvm
      @rockthejvm  3 года назад +1

      Glad it helped - although it's just me :D

  • @obafemiteminife
    @obafemiteminife 3 года назад +2

    Another helpful tutorial🤗
    Many thanks
    Keep it up💪

  • @user-jt9km4jv5k
    @user-jt9km4jv5k 3 года назад +1

    Another great video. Thanks!

  • @bilalf
    @bilalf 3 года назад +1

    ❤️ ❤️ ❤️ ❤️ ❤️

  • @mangos1346
    @mangos1346 3 года назад +1

    The generics doesnt necessarily mean it has to be directly from the type argument. Both OOP and FP can use generics. The sample is simply type lambda that takes a type argument as a generic type.

    • @rockthejvm
      @rockthejvm  3 года назад

      The argument was not between OOP vs FP. It was purely from the perspective of how the compiler validates the types.

  • @rokkralj9786
    @rokkralj9786 3 года назад +1

    Nit: why s.charAt(s.length - 1). s.last works on strings. And last methods already throw NoSuchElementException, no need to check and rethrow.

  • @btcvibes1436
    @btcvibes1436 Год назад

    How can we write lastComponentOf so that it returns Either instead of throwing exceptions?

  • @indianbullet
    @indianbullet 2 года назад

    I was able to write accumulate in this manner:
    def accumulate[T](accumulator: T, value: ConstituentPartOf[T]): T = (accumulator match
    case b: BigInt => b + value.asInstanceOf[ConstituentPartOf[BigInt]]
    case s: String => s + value.asInstanceOf[ConstituentPartOf[String]]
    case l: List[_] => value.asInstanceOf[ConstituentPartOf[l.type]] :: l).asInstanceOf[T]
    Not incredibly concise for the function author with all of the compiler hints, but I believe still type-safe as far as the user is concerned.
    EDIT:
    Turns out there is no real compiler safety here inside the function itself, as I was able to add this nonsensical case: `case d: Double => d + value.asInstanceOf[ConstituentPartOf[String]]`. But as the "library" user, you would not be able to call the function in a way to actually exercise that case.

  • @HoD999x
    @HoD999x Год назад

    about 10:35 - you said this is not possible in scala 2, but what about just implementing 3 methods instead of one case block? it's 100% compile time safe.

    • @rockthejvm
      @rockthejvm  Год назад

      But it doesn't provide the same info, does it?

  • @kotobotov
    @kotobotov 3 года назад +1

    what about using method overloading in scala 2?

    • @rockthejvm
      @rockthejvm  3 года назад

      What about method overloading?

    • @kotobotov
      @kotobotov 3 года назад

      @@rockthejvm seems to be possible return different result for different argument in the same method

    • @rockthejvm
      @rockthejvm  3 года назад

      @@kotobotov Yep - something confusing?

  • @Jankoekepannekoek
    @Jankoekepannekoek Год назад

    can't you use GADTs for flow typing?

  • @anticipayo
    @anticipayo 3 года назад

    I like this solution. My only concern is that it doesn't seem extensible. Perhaps extensible match types will be part of scala 3.1?

    • @rockthejvm
      @rockthejvm  3 года назад

      What do you mean by extensible in this case?

    • @valcron-1000
      @valcron-1000 3 года назад

      @@rockthejvm I have the same concern. When you define the match type there's no way to extend it to new types (ConstituentPartOf is "closed") after it was defined. The "lastComponentOf" function is "closed" since I can't extend it without modifying the function itself (adding another case)
      I'm not too familiar with Scala (mostly Haskell) but couldn't you get the same behavior using type classes? Defining something like "ConstituentPartOf[A,B] where lastComponentOf[A, B](src: A): B" (not sure about the syntax btw)

    • @anticipayo
      @anticipayo 3 года назад

      @@rockthejvm What if i want to extend a match type to match more distinct pair of types, but in a different file? How would you do that? Everything seems to require to be inside one big match statement

  • @johnlofgren6089
    @johnlofgren6089 3 года назад

    Great video, thanks! For me as a client of your awesome new lastComponentOf API, can I extend the API to other types? For example, suppose I want to be able to get lastComponentOf a SortedMap. Is there a way for me to add that functionality without modifying your library?

    • @rockthejvm
      @rockthejvm  3 года назад

      This use-case assumes you're offering the library under a single API, so if you want to support an additional type, you can add cases in the match type + implementation and your single API will still work.

    • @johnlofgren6089
      @johnlofgren6089 3 года назад

      @@rockthejvm I think this presumes that I have access to the library source code. I'm asking if there is any way to extend the type match if I DON'T have access to modify the library code. (I'm guessing the answer is no, that's what type classes are for?)

  • @vicc8881
    @vicc8881 3 года назад +1

    Another great video. Thanks!