<https://twitter.com/raulraja/status/1275744359019...
# arrow-meta
r
j
Refined types look amazing! What is the typical use-case for Union types? I see it in TypeScript as well, but have not used it -it's like that amazing tool in your toolbox that you never use because you've been doing things differently all these years until somebody points out you can use that tool to make life easier, then you can't live without it (likewise with Either, Optics, Delegates, using them daily now whereas before they were just tools that i thought i didn't need)
m
Union types are a more flexible implementation of sum types than Kotlin's sealed classes. If you have a large number of sealed classes that describe related entities, you will have to 1) define a new type for a given entity to make it part of yet another sum type (if "x" can be a case of S1 and S2, S1.X and S2.X will be two different types) , and/or 2) nest sealed classes very deeply because you can't "merge" them or "extend" them (if you want S2 with all cases of S1 and also the case "z", you will probably end up making S2 the sum of, say, Y which is the case where S2 is one of the cases in S1 and thus contains a reference to a S1, and Z which represents "z"). When describing complex systems, this can degenerate pretty quickly. This is because sealed classes represent only types which are the sum of their subclasses, while union types represent types which are the sum of arbitrary types.
j
What would be a practical example of this where the benefit is extremely well illustrated? All the use-cases i can think of, there are other ways of solving it that aren't terrible like using method overloading instead of accepting a union type or is this more a case of being able to have classes that are more closely aligned with a business model?
r
An example would be when you have to wrap primitives and platform types like Int and String. You can’t extend those and if you want a Sum type around them you need to pay the allocation cost of wrapping those in a sealed hierarchy. If union made it to the lang those would have no allocation cost.
Copy code
val x : String | Int = 0
vs
Copy code
sealed class StringOrInt()
data class StringWrapper(val s: String): StringOrInt()
data class IntWrapper(val n: Int): StringOrInt()
j
ok, that second one looks quite messy, thanks for the example! so i can see it being used for very complex modelling then, so instead of creating a new type in order to wrap two / three / ... types, your method signature now only contains the union type instead of a wrapper for all the types it can accept or instead of an overloaded function that has 10 different functions due to it accepting 10 different types i'm assuming TypeAliases would be allowed with Union types as well? Building something like a BPMN system now becomes much easier or even users using it, instead of it accepting Any it explicitly allows you to specify what it accepts Maybe even useful in DSLs, HEAD tag can accept META, SCRIPT, etc instead of having a common class from which HEAD, SCRIPT, etc is extending from.
Copy code
typealias Number = Int | Float | Double | BigInt | BigDecimal
ok, i think the lightbulb is going on, this is looking very useful! typealias Size = EM | CM | MM | IN | PT | PC | '%' | PX | EX fun resizeDiv(size: Size) ... resizeDiv(1.px) resizeDiv(20.'%')
😉 1