功能上相当于重载

发布于 2024-11-14 20:02:30 字数 593 浏览 2 评论 0原文

在函数式编程中我应该采取什么方法来重载方法(提供一个或多个具有相同函数名称的不同签名)。

我是函数式编程的新手,所以目前我还没有真正理解这一点。

例如,在 C# 中,我有以下内容:

public int LowestCommonMultiple(int a, int b)
{
    return (a * b) / GreatestCommonFactor(a, b); // details ommited
}

public int LowestCommonMultiple(List<int> integers)
{
    int commonMultiple = integers[0];
    foreach(var integer in integers)
    {
        commonMultiple = LowestCommonMultiple(commonMultiple, i);
    }
    return commonMultiple;
}

谢谢,

编辑:我不需要 C# 中的答案,我的问题更多的是函数式 pargadim 问题,例如,在 Haskell 中考虑它。我认为重载方法不是一种选择。

What is the approach I should be taking in functional programming to overload a method (provide one or more different signatures with the same function name).

I'm new to functional programming, so I don't really get my head around this at the moment.

For example, in C# I'd have the following:

public int LowestCommonMultiple(int a, int b)
{
    return (a * b) / GreatestCommonFactor(a, b); // details ommited
}

public int LowestCommonMultiple(List<int> integers)
{
    int commonMultiple = integers[0];
    foreach(var integer in integers)
    {
        commonMultiple = LowestCommonMultiple(commonMultiple, i);
    }
    return commonMultiple;
}

Thanks,

EDIT: I don't need the answer in C#, my question is more a functional pargadim question, for example, consider it in Haskell. I assume overloading a method is not an option.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

奈何桥上唱咆哮 2024-11-21 20:02:30

在 Haskell 中,重载是使用类型类完成的。这与 C# 中的重载有很大不同,因为类型类与 C# 中的接口更相似,尽管它们也更强大*。

例如,要拥有一个能够接受 IntegerBool 的函数,您可以编写如下内容:

class Foo a where
    foo :: a -> String

instance Foo Integer where
    foo n = show (n+42)

instance Foo Bool where
    foo b = if b then "Hello" else "Goodbye"

在解释器中测试它,我们看到函数 foo 具有带有约束的类型。

*Main> :t foo
foo :: Foo a => a -> String

这意味着该函数适用于我们为其定义了 Foo 实例的类型 a

*Main> foo 1295
"1337"
*Main> foo False
"Goodbye"

如果我们尝试在没有此类实例的类型上使用它,我们会收到错误。

*Main> foo "Hello"

<interactive>:1:1:
    No instance for (Foo [Char])
      arising from a use of `foo'
    Possible fix: add an instance declaration for (Foo [Char])
    In the expression: foo "Hello"
    In an equation for `it': it = foo "Hello"

对于你的例子,我认为在 Haskell 中以这种方式重载这个函数不是很有用。事实上,标准库中的lcm函数已经被重载了。

*Main> :t lcm
lcm :: Integral a => a -> a -> a

这意味着它适用于任何有 Integral 实例的类型。在本例中,这就是所有类似整数的类型,包括机器大小的 Int、任意大小的 Integer 以及其他类型,例如 Int32Int64 等等。

列表版本可以写为 foldl1' lcm,因此可能不需要首先提供这样的重载。

* 一方面,类型类实例与它们所应用的对象分开传递。这使得多重调度之类的事情变得更加清晰。这也意味着您可以重载函数的返回类型,这在 C# 中是不可能的。类型类也可以与类型构造函数一起使用; Monad 也许是此类类型中最著名的示例。

In Haskell, overloading is done using type classes. This is quite different from overloading in C#, as type classes are more similar to interfaces in C#, although they are also more powerful*.

For example, to have a function which will be able to accept either an Integer or a Bool, you can write something like this:

class Foo a where
    foo :: a -> String

instance Foo Integer where
    foo n = show (n+42)

instance Foo Bool where
    foo b = if b then "Hello" else "Goodbye"

Testing this out in the interpreter, we see that the function foo has a type with constraints.

*Main> :t foo
foo :: Foo a => a -> String

This means that the function will work for types a for which we have defined a Foo instance.

*Main> foo 1295
"1337"
*Main> foo False
"Goodbye"

If we attempt to use it on a type for which there is no such instance, we get an error.

*Main> foo "Hello"

<interactive>:1:1:
    No instance for (Foo [Char])
      arising from a use of `foo'
    Possible fix: add an instance declaration for (Foo [Char])
    In the expression: foo "Hello"
    In an equation for `it': it = foo "Hello"

For your example, I don't think it's very useful to overload this function in such a way in Haskell. In fact, the lcm function in the standard library is already overloaded.

*Main> :t lcm
lcm :: Integral a => a -> a -> a

This means that it will work on any type for which there is an Integral instance. In this case, that's all integer-like types, including the machine-sized Int, the arbitrary-size Integer, and others such as Int32, Int64 and so on.

The list version can be written as foldl1' lcm, so there might not be much of a need to provide such an overload in the first place.

* For one thing, type class instances are passed separately from the objects they apply to. This makes things like multiple dispatch a lot cleaner. This also means you can overload on the return type of a function, which would be impossible in C#. Type classes can also be used with type constructors; Monad is perhaps the most famous example of such a type class.

几度春秋 2024-11-21 20:02:30

我不确定你所说的函​​数式编程语言是什么意思,这似乎与任何编程语言的特定功能(例如,支持重载)有关,而不是它是函数式的还是面向对象的。例如,在 Javascript 中,它不受支持,但很容易模拟,因为 javascript 不需要传递参数并且不是强类型的。

// a: array or integer
// b: optional integer when a is integer
function LowestCommonMultiple(a, b)
{
    // could also test for presence of b, other validation checking probably good
    if (a instanceof Array) {
       // array code
    } else {
       return (a * b) / GreatestCommonFactor(a, b); // details ommited
    }
}

答案将取决于所讨论语言的具体功能。

I'm not sure what you mean by a functional programming language, this seems to have to do with a specific feature of any programming language (e.g., is overloading supported) rather than whether it is functional or object-oriented. In Javascript, for example, it is not supported, but is easily simulated because javascript doesn't require parameters to be passed and isn't strongly typed.

// a: array or integer
// b: optional integer when a is integer
function LowestCommonMultiple(a, b)
{
    // could also test for presence of b, other validation checking probably good
    if (a instanceof Array) {
       // array code
    } else {
       return (a * b) / GreatestCommonFactor(a, b); // details ommited
    }
}

The answer is going to be depend on the specific features of the language in question.

我喜欢麦丽素 2024-11-21 20:02:30

我认为你的问题与函数式编程与过程式/面向对象编程没有太大关系,而是与静态变量类型与动态变量类型有关。

以SML(ML的一种方言)和Scheme/Lisp为例。两种函数式语言,但是在 SML 中重载函数是理所当然的,而在Scheme 中则不可能(至少在我还在使用它时是这样)。
SML 是静态类型的(如 C/C++/JAVA 等),因此编译器使用变量类型作为签名的一部分并创建重载不是问题,就像任何 C 编译器为 C 代码创建它们一样。另一方面,Scheme 是动态类型的,因此编译器/解释器无法在编译时(在大多数情况下)根据其参数找出方法的签名。

你的问题是非常跨语言的(我什至不认为所有静态类型语言都支持函数/方法重载),所以它总是取决于你使用的语言(有时是实现)。

I don't think that your problem has much to do with functional vs procedural/OO programing but with static vs dynamic variable typing.

Take SML (a dialect of ML) and Scheme/Lisp for instance. Both functional languages, but it's a no brainer to overload a function in SML while it's impossible in Scheme (at least so it was when I was still using it).
SML is statically typed (like C/C++/JAVA etc.) and therefore it's not problem for the compiler to use the variable types as a part of the signature and create overloads just like you any C compiler would create them for C code. Scheme on the other hand is dynamically typed and therefore the compiler/interpreter can't figure out a signature for the method based on it's parameters at compile time (in most cases).

Your question is very language pacific (I don't even think that all statically typed languages support function/method overloading) so it'll always come down to what language (and sometimes implementation) are you using.

枕花眠 2024-11-21 20:02:30

您可以通过一次重构编写任意数量的签名 - 不能有 2 个具有相同参数类型的签名。每个签名都可以有它自己的返回类型

void SomeMethor(){...}
string SomeMethod(string s){...}
object SomeMethod(string s, int i){...}

you can write any count of signatures with one restruction - you can't have 2 signatures with equal parameter types. Every signature can have it's ow return type

void SomeMethor(){...}
string SomeMethod(string s){...}
object SomeMethod(string s, int i){...}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文