当我第一次学习Haskell时,我很快就开始喜欢参数多态.这是一个令人愉快的简单想法,工作得非常好.整个"如果它编译它通常工作正常"的事情主要是由于参数多态,恕我直言.
但是前几天,我发生了一件事.我可以写成foo
多态函数.但是当bar
调用时foo
,它将使用一组特定的参数类型来完成.或者,如果bar
它本身是多态的,那么它的调用者将分配确定的类型.通过归纳,似乎如果您要采用任何有效的Haskell程序并分析整个代码库,您可以静态地确定整个程序中每个事物的类型.
从某种意义上说,这有点像C++模板.没有运行时多态,只有编译时多态.Haskell编译器可以选择为每个调用每个多态函数的类型生成单独的机器代码.大多数Haskell编译器没有,但如果你愿意,你可以实现一个.
只有当你开始添加Haskell扩展(ExistentialQuantification
显而易见的是)时,你才开始获得真正的运行时多态性,你可以在其中获得无法静态计算类型的值.
哦,是的,我的问题?
以上陈述是否真的正确?
这个属性有广泛使用的名称吗?
基于我读过的关于Haskell的内容,以及我用GHC做过的实验,似乎Haskell有返回类型重载(又称ad hoc多态).这方面的一个例子是fromInteger
可以给你一个Double
或一个Integer
取决于结果使用位置的函数.例如:
fd :: Double -> String
fd x = "Double"
fi :: Integer -> String
fi x = "Integer"
fd (fromInteger 5) -- returns "Double"
fi (fromInteger 5) -- returns "Integer"
Run Code Online (Sandbox Code Playgroud)
Haskell的一个温和的介绍似乎同意这一点,当它说:
到目前为止我们讨论过的那种多态性通常被称为参数多态.另一种称为ad hoc多态,更好地称为重载.以下是ad hoc多态的一些示例:
- 文字1,2等通常用于表示固定和任意精度整数.
如果数字文字被认为是ad hoc多态(也就是重载)的一个例子,那么似乎对于函数的结果也是如此fromInteger
.
事实上,我已经找到了一些关于Stack Overflow的其他问题的答案,这些问题表明Haskell通过返回类型进行了重载.
但是,至少有一个Haskell程序员告诉我这不是返回类型重载,而是"参数多态,其中参数受通用量词约束"的示例.
我认为他所得到的是fromInteger
从每个实例Num
(某种非确定性类型)返回一个值.
这似乎是一个合理的解释,但据我所知,Haskell从不让我们看到这些实例值中的多个(部分归功于Monomorphism限制).我们看来的实际情况似乎也可以静态确定.由于所有这一切,似乎有理由说在表达式fd (fromInteger 5)
中子表达式fromInteger 5
是类型Double
,而在表达式fi (fromInteger 5)
中子表达式fromInteger 5 …