【问题标题】:How to work around rank N polymorphism in C#?如何解决 C# 中的 N 级多态性?
【发布时间】:2017-08-06 08:31:24
【问题描述】:

假设有一个恒等函数,即:

T Id<T>(T t) { return t; }

我应该输入什么F

void F<T>(Func<T, T> f) { // This is not sound!
    System.Console.WriteLine("{0}", f(1));
    System.Console.WriteLine("{0}", f("one"));
}

static void Main() {
    F(Id);
}

我认为 C# 没有 N 级多态性,C# 不能正确键入 F。是这样吗?

然后如何解决这些问题?

【问题讨论】:

  • 你需要详细说明,很多。确实,您发布的代码不起作用。但是你为什么要让它工作呢?您的“通用”方法仅使用 T 来调用 f 委托。您可以轻松地声明方法void F(Func&lt;object, object&gt; f) { ... },它会起作用。
  • void F(Func&lt;object, object&gt; f) { ... } 不是类型安全的。如果F 有这样的类型,f 可以是string Foo(int v) { return v + ""; }
  • 从表面上看,这似乎是一个关于 C# 语言不支持的功能的学术问题。能给个实际用例吗?
  • 我正在尝试将 Sprache(解析器组合库)转换为 CPS,并引用 attoparsec(Haskell 中的解析器组合器)。

标签: c# type-systems rank-n-types


【解决方案1】:

我不清楚您要实现什么,但您可以使用包含泛型方法的非泛型接口来做到这一点:

using System;

interface IGenericSameTypeFunction
{
    T Apply<T>(T input);
}

public class SimpleIdentityFunction : IGenericSameTypeFunction
{
    public T Apply<T>(T input) => input;
}

class Test
{    
    static void F(IGenericSameTypeFunction function)
    {
        Console.WriteLine(function.Apply(1));
        Console.WriteLine(function.Apply("one"));
    }

    static void Main()
    {
        F(new SimpleIdentityFunction());
    }
}

重要的一点是,通过将Apply 方法设为泛型而不是F 方法,您就是在说“这是一个可以以类型安全的方式应用于任何类型的函数。”

虽然没有办法将该接口表示为委托类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2021-09-21
    • 2013-03-28
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    相关资源
    最近更新 更多