首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Haskell不支持具有不同类型的函数共享公共名称的C++重载样式。

Haskell不支持具有不同类型的函数共享公共名称的C++重载样式。
EN

Stack Overflow用户
提问于 2016-04-14 14:33:01
回答 3查看 218关注 0票数 3

我在学习Haskell。当我看了下面的文档。https://www.haskell.org/tutorial/classes.html

有人提到"Haskell不支持C++重载风格,在这种风格中,不同类型的函数共享一个共同的名称。“我不明白这句话,我想ad多态性(它是通过使用类型类完成的)相当于C++,Java中的方法重载。有人能告诉我我的理解是正确的吗?

代码语言:javascript
运行
复制
class Equal a where

    isEquals :: a -> a -> Bool


type Id = Int
type Name = String

data Employee = Engineer Id Name 

data Student = Student Id Name

getEmpId (Engineer empId _) = empId
getStudId (Student studId _) = studId

instance Equal Employee where
    isEquals emp1 emp2 = getEmpId emp1 == getEmpId emp2

instance Equal Student where
    isEquals stud1 stud2 = getStudId stud1 == getStudId stud2

在上面的代码段中,“isEquals”函数被应用于两种不同类型的Employee,Student,它相当于C++,Java中的重载。我的理解正确吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-04-14 14:41:06

部分是的。但是,请记住,isEquals的签名始终是a -> a。在C++中,您可以轻松地编写:

代码语言:javascript
运行
复制
int foo(int a, int b)
int foo(int a, char b)
int foo(char a, char b)

通过使用类型化,你只能得到第一和第三个函数,而不是第二个。

更新1:

正如注释中所指出的,您可以通过使用MultiParamTypeClasses扩展(如果您正在使用GHC)来实现第二个版本。不过,还有第四种版本:

代码语言:javascript
运行
复制
int foo(int a, int a, int a)

如果使用类型类型,这是错误的,但在C++中是完全正确的。

票数 2
EN

Stack Overflow用户

发布于 2016-04-15 13:09:40

Haskell中的类型类只是提供隐式参数的一种奇特方法。请考虑以下代码:

代码语言:javascript
运行
复制
data Equal a = Equal {isEquals :: a -> a -> Bool}


type Id = Int
type Name = String

data Employee = Engineer Id Name 

data Student = Student Id Name

getEmpId (Engineer empId _) = empId
getStudId (Student studId _) = studId

equalEmployee :: Equal Employee
equalEmployee = Equal {
    isEquals = \emp1 emp2 -> getEmpId emp1 == getEmpId emp2
}

equalStudent :: Equal Student
equalStudent = Equal {
    isEquals stud1 stud2 = getStudId stud1 == getStudId stud2
}

equalThree :: Equal a -> a -> a -> a -> Bool
equalThree e a1 a2 a3 = isEquals e a1 a2 && isEquals e a2 a3

你的代码有什么不同?如果在你的代码中我们定义

代码语言:javascript
运行
复制
equalThree :: Equal a => a -> a -> a -> Bool
equalThree a1 a2 a3 = isEquals a1 a2 && isEquals a2 a3

不同之处在于,在您的代码(有类)中,编译器使用给定的类型自行找到一个合适的类实例。在我的变体中,显式地提供了必需的实例。但这是唯一的区别,事实上,你的变体会被转换成我的引擎盖下。

因此,类不覆盖任何内容。它们只是数据类型和隐式参数的高级语法。

票数 0
EN

Stack Overflow用户

发布于 2016-04-15 15:26:18

不怎么有意思。获得与C++等价的唯一方法(函数;Haskell没有方法!)重载是一个类型类。

代码语言:javascript
运行
复制
class SomeFunc a where
    someFunc :: a

现在,您可以在(或多或少)任何类型中定义someFunc。但是,您必须为每个要“重载”的函数声明它,而在C++中,这只是因为有两个名称相同的函数就意味着这一点。

Haskell的类型系统旨在提供C++没有的东西:标准化行为(表示为法律)。

代码语言:javascript
运行
复制
class Eq a where
    (==), (/=) :: a -> a -> Bool

现在您知道了语言中的每个==操作符都有两个相同类型的参数,并返回一个布尔值;相比之下,C++非常好,类似于

代码语言:javascript
运行
复制
mystring operator (==)(mystring x, string y) {
    return x + " == " + y;
}

这违反了所有那些“合理”的规则。除此之外,类型类还有规律。

代码语言:javascript
运行
复制
x == x = True -- x total
x == y = y == x
x == y = True => y == z = True => x == z = True

这是对所有实例的附加限制。每个实例都是这个类型类的一个实例(定义在一个地方),这给您提供了一个地方来定义这些规则,这使得这一事实更加容易。在C++中,这样的“法律”更具有公约的性质。此外,C++被明确设计为允许使用+进行字符串连接,而Haskell则明确地设计为dis-允许类似的事情(这可能是'Haskell不支持C++重载风格‘的意思),因此法律必须在C++中有更多的约定的特征,如果方便的话,单个类型可以忽略它们。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36626313

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档