9 Comments
User's avatar
Lars Eckart's avatar

such union types is also something I really liked when learning elm (https://guide.elm-lang.org/types/custom_types.html). in java, we would model this with an interface and both ResolvableLink and UnresolvableLink implementing it?

Kevin Rutherford's avatar

Yes, in Java one would use an interface as you suggest. (I also had a comment via email saying the same as you.) The problem then is that both the Java interface solution and the Typescript union type solution lose information -- the type of the item added to the list is lost at runtime and can't easily be recovered by code when it retrieves those items again.

Philip Schwarz's avatar

I had a go at some Java

```java

import java.util.List;

sealed interface Link { }

record ResolvableLink(String title, String url) implements Link { }

record UnresolvableLink(String title) implements Link { }

class Main {

public static void main(String[] args) {

List<Link> listOfLinks = List.of(

new ResolvableLink("Habitable Code", "https://habitablecode.substack.com/"),

new UnresolvableLink("Free Money")

);

System.out.println("Links=" + listOfLinks);

}

}

```

Philip Schwarz's avatar

Here is a Scala union type example:

type Link = UnresolvableLink | ResolvableLink

case class ResolvableLink(title: String, url: String)

case class UnresolvableLink(title: String)

val listOfLinks = List[Link](

ResolvableLink(title = "Habitable Code", url = "https://habitablecode.substack.com/"),

UnresolvableLink(title = "Free Money")

)

println(s"Links=$listOfLinks")

==>

Links=List(ResolvableLink(Habitable Code,https://habitablecode.substack.com/), UnresolvableLink(Free Money))

Philip Schwarz's avatar

FWIW, here is a Scala example with a Link ADT (Algebraic Data Type)

type ListOfLinks = List[Link]

enum Link:

case ResolvableLink(title: String, url: String)

case UnresolvableLink(title: String)

import Link._

val listOfLinks = List(

ResolvableLink("Habitable Code", "https://habitablecode.substack.com/"),

UnresolvableLink("Free Money")

)

println(s"Links:$listOfLinks")

Philip Schwarz's avatar

FWIW, here is a Scala example using Either:

type Link = Either[UnresolvableLink,ResolvableLink]

case class ResolvableLink(title: String, url: String)

case class UnresolvableLink(title: String)

val listOfLinks = List[Link](

Right(ResolvableLink(title = "Habitable Code", url = "https://habitablecode.substack.com/")),

Left(UnresolvableLink(title = "Free Money"))

)

println(s"Links=$listOfLinks")

Philip Schwarz's avatar

Hello Kevin.

Do you think you could elaborate, e.g. with example(s), on what you mean by 'only run-time checks will tell me that something has broken' and 'I want to be able to see their dependencies locally, without having to execute the code.'

I am asking so that I can better understand what the problem is and also whether the reason why 'run-time' is being mentioned has anything to do with weak/strong typing and/or static/dynamic typing.

Kevin Rutherford's avatar

In a way @Philip those phrases are my "north star" for this newsletter. I'm writing in order to understand what they mean and to attempt to discover whether they are achievable.

I did expend a little more in a later post https://habitablecode.substack.com/p/runtime-and-compile-time, but you're right -- there's a lot more to be said and a lot more exploration needed.

Philip Schwarz's avatar

All right, I'll be working my way through the posts and will get to that one.

Thanks.