我在学习Haskell。当我看了下面的文档。https://www.haskell.org/tutorial/classes.html
有人提到"Haskell不支持C++重载风格,在这种风格中,不同类型的函数共享一个共同的名称。“我不明白这句话,我想ad多态性(它是通过使用类型类完成的)相当于C++,Java中的方法重载。有人能告诉我我的理解是正确的吗?
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中的重载。我的理解正确吗?
发布于 2016-04-14 14:41:06
部分是的。但是,请记住,isEquals的签名始终是a -> a。在C++中,您可以轻松地编写:
int foo(int a, int b)
int foo(int a, char b)
int foo(char a, char b)通过使用类型化,你只能得到第一和第三个函数,而不是第二个。
更新1:
正如注释中所指出的,您可以通过使用MultiParamTypeClasses扩展(如果您正在使用GHC)来实现第二个版本。不过,还有第四种版本:
int foo(int a, int a, int a)如果使用类型类型,这是错误的,但在C++中是完全正确的。
发布于 2016-04-15 13:09:40
Haskell中的类型类只是提供隐式参数的一种奇特方法。请考虑以下代码:
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你的代码有什么不同?如果在你的代码中我们定义
equalThree :: Equal a => a -> a -> a -> Bool
equalThree a1 a2 a3 = isEquals a1 a2 && isEquals a2 a3不同之处在于,在您的代码(有类)中,编译器使用给定的类型自行找到一个合适的类实例。在我的变体中,显式地提供了必需的实例。但这是唯一的区别,事实上,你的变体会被转换成我的引擎盖下。
因此,类不覆盖任何内容。它们只是数据类型和隐式参数的高级语法。
发布于 2016-04-15 15:26:18
不怎么有意思。获得与C++等价的唯一方法(函数;Haskell没有方法!)重载是一个类型类。
class SomeFunc a where
someFunc :: a现在,您可以在(或多或少)任何类型中定义someFunc。但是,您必须为每个要“重载”的函数声明它,而在C++中,这只是因为有两个名称相同的函数就意味着这一点。
Haskell的类型系统旨在提供C++没有的东西:标准化行为(表示为法律)。
class Eq a where
(==), (/=) :: a -> a -> Bool现在您知道了语言中的每个==操作符都有两个相同类型的参数,并返回一个布尔值;相比之下,C++非常好,类似于
mystring operator (==)(mystring x, string y) {
return x + " == " + y;
}这违反了所有那些“合理”的规则。除此之外,类型类还有规律。
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++中有更多的约定的特征,如果方便的话,单个类型可以忽略它们。
https://stackoverflow.com/questions/36626313
复制相似问题