Hacker News new | ask | show | jobs
by shiandow 305 days ago
If you're creative about it you can make an interface for what is essentially a sum type.

All it takes is a method signature like:

   Z read<Z>(Func<A,Z> readA, Func<B,Z> readB)
It's a bit of a Yoneda embedding like way of forcing it in to the language, but hey it works.
2 comments

I think I'm missing something.

Presumably, you use a function like this to represent your sum type containing the value "avalue":

    (readA, readB) => readA(avalue)
The problem I have is that when you create this function you have to reify the return type Z. You can't use this value in arbitrary contexts where the accessors need to return different types.

How do you get this to work?

You want to return different types depending on the branch?

I mean you could return a sum type if you really need to.

Formally a sum type is just something that turns a pair of functions to Z into a single function from the sum type to Z. In fact it shouldn't do more than that.

No, in any particular use of the value both branches return the same type Z.

But when I want to use the value in two different places I don't want Z to be the same in both places.

That's where I'm stuck. When I instantiate the function that represents a value of the sum type I need to choose a return type Z, which is locked in for every use of the value.

I think I understand the idea. I don't see how to make it work in C#.

Yep, this is exactly the approach we take. It works ok-ish, but it’s far from elegant. In our case ‘read’ is ‘Switch’. I think it’s a fairly common pattern in C# these days.