Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Better pattern matching with generic types #16156

Closed
gulshan opened this issue Dec 30, 2016 · 10 comments
Closed

Proposal: Better pattern matching with generic types #16156

gulshan opened this issue Dec 30, 2016 · 10 comments

Comments

@gulshan
Copy link

gulshan commented Dec 30, 2016

Predecessor: #5023

Actually in the parent issue, pattern matching was not highlighted. Hence this new issue. Given these classes-

abstract class Result<T> { }
sealed class Success<T>:Result<T>
{
    public T Value {get;}
    public Success(T value) {Value = value;}
}
sealed class Error<T>:Result<T>
{
    public Exception Ex {get;}
    public Error(Exception ex) {Ex = ex;}
}

And this static method-

static Result<T> Try<T>(Func<T> fun)
{
    try
    {
        return new Success<T>(fun());
    }
    catch (Exception e)
    {
        return new Error<T>(e);
    }
}

I want to write

var res = Try(SomeMethod);
if (res is Success ok)
    Console.WriteLine(ok.Value);
else
    Console.WriteLine((res as Error).Ex.Message);

instead of

var res = Try(SomeMethod);
if (res is Success<int> ok)
    Console.WriteLine(ok.Value);
else
    Console.WriteLine((res as Error<int>).Ex.Message);

Another option can be discarding the type with '_'-

var res = Try(SomeMethod);
if (res is Success<_> ok)
    Console.WriteLine(ok.Value);
else
    Console.WriteLine((res as Error<_>).Ex.Message);
@HaloFour
Copy link

HaloFour commented Dec 30, 2016

Look at #6739, specifically the use of enums as algebraic data types. The Option<T> example is very similar to your Result<T> use case.

Assuming that syntax is adopted as-is, you'd probably work with it as follows:

public enum class Result<T> {
    Success(T result),
    Error(Exception error)
}

Result<T> result = ...; // calculate some result here
if (result is Success(var value)) { ... }
else if (result is Error(var error)) { ... }

@gulshan
Copy link
Author

gulshan commented Dec 30, 2016

Is the pattern matching with generic types coming included with it?

@HaloFour
Copy link

That proposal won't be implemented for C# 7.0, which is more or less feature complete now. I expect that pattern matching will be expanded upon over several releases of the language, hopefully more point releases than new versions.

@gafter
Copy link
Member

gafter commented Dec 30, 2016

@gulshan Can you please show what kind of code the compiler would translate this into?

@jnm2
Copy link
Contributor

jnm2 commented Dec 30, 2016

I keep seeing the title and thinking "ooh, genetic types, what's that?"

@gulshan
Copy link
Author

gulshan commented Jan 5, 2017

@gafter I'm not sure if this can be done with code generation. Now I realize there may be several steps for this proposal-

  • First, it's more about the pre-"Pattern Matching" is operator working with the bare generic types- instead of requiring them to specify type arguments. From my example, that will make result is Success a valid expression instead of requiring result is Success<int> or throwing Error CS0305.
  • Then this behavior should work with as operator, infering the type argument. result as Success should be infered to (or code generated to) result as Success<int> infering the int as the type argument.
  • Lastly, translating this concept naturally to pattern matching- making result is Success ok code generated to result is Success<int> ok.

@HaloFour
Copy link

HaloFour commented Jan 5, 2017

@gulshan

The "bare" generic type for Success<int> would be Success<T> or Success<>, not Success. Success would be a completely different type.

// all legal and different types
public class Success { }
public class Success<T> { }
public class Success<T1, T2> { }

For the C# compiler to assume that Success meant Success<T> or Success<T1, T2> would lead to all kinds of ambiguity problems.

@gulshan
Copy link
Author

gulshan commented Jan 5, 2017

Then it can be Success<_> as stated at the end of my proposal, or Success<*>. But I really want it to be parameterless Success, if the ambiguity is somehow resolvable- like prioritizing types with less (or no) generic type parameters.

@MgSam
Copy link

MgSam commented Jan 5, 2017

I keep seeing the title and thinking "ooh, genetic types, what's that?"

@jnm2 Genetic types are great for inheritance.

@gulshan gulshan changed the title Proposal: Better pattern matching with genetic types Proposal: Better pattern matching with generic types Jan 5, 2017
@gulshan
Copy link
Author

gulshan commented Feb 28, 2018

Discussion is on- dotnet/csharplang#268

@gulshan gulshan closed this as completed Feb 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants