根据我所读到的关于Haskell的内容,以及我对GHC所做的实验,Haskell似乎有返回类型重载(又名即席多态)。这方面的一个例子是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"哈斯克尔的绅士介绍似乎同意这一点,它说:
到目前为止,我们讨论过的那种多态性通常被称为参数多态性。还有另一种叫做即席多态( ad多态),也就是所谓的重载。以下是一些临时多态的例子:
如果数字文本被认为是即席多态(也称为重载)的一个例子,那么像fromInteger这样的函数的结果似乎也是如此。
事实上,我已经找到了一些关于堆栈溢出的其他问题的答案,这些答案表明Haskell有返回类型的重载。
然而,至少有一个Haskell程序员告诉我,这不是返回类型重载,而是一个“参数多态,参数被一个通用量词绑定”的例子。
我认为fromInteger正在从Num的每个实例中返回一个值(某种程度上是不确定的类型)。
这似乎是一种合理的解释,但据我所知,Haskell从来不让我们查看其中的多个实例值(部分归功于单态限制)。我们所看到的实际实例的值也可以静态地确定。由于所有这些,似乎可以合理地说,在表达式fd (fromInteger 5)中,子表达式fromInteger 5为Double类型,而在表达式fi (fromInteger 5)中,子表达式fromInteger 5为Integer类型。
那么,Haskell有返回类型重载吗?
如果没有,请举例说明以下情况之一:
发布于 2012-07-10 19:14:26
可以这样看,Haskell将您正在考虑的返回类型多态性转换为参数多态,使用的是字典--为类型类传递翻译。(尽管这不是实现类型类的唯一方法,也不是实现它们的原因;它只是最流行的方法。)
基本上,fromInteger在Haskell中有这种类型:
fromInteger :: Num a => Integer -> a它可能在内部被翻译成这样的东西:
fromInteger# :: NumDictionary# a -> Integer -> a
fromInteger# NumDictionary# { fromInteger = method } x = method x
data NumDictionary# a = NumDictionary# { ...
, fromInteger :: Integer -> a
, ... }因此,对于每个带有T实例的具体类型,都有一个包含函数fromInteger :: Integer -> T的NumDictionary# T值,所有使用Num类型类的代码都被转换为以字典为参数的代码。
发布于 2012-07-10 19:23:14
关于Haskell式打字机的开创性论文叫做如何使即席多态性减少即席性.所以,对你的问题的回答是有条件的“是”--取决于你要求你的返回类型重载的临时程度.
换句话说:毫无疑问,特设多态与类型分类相关,因为这是发明它们的一个有动机的例子。但是,你是否认为这个结果仍然符合“返回类型重载”的资格,取决于你喜欢的定义的微妙细节。
发布于 2012-07-10 21:32:10
我想谈一谈你问题的一小部分:
我们所看到的实际实例的值也可以静态地确定。
这并不是很准确。考虑以下古怪的数据类型:
data PerfectlyBalancedTree a
= Leaf a
| Branch (PerfectlyBalancedTree (a,a))
deriving (Eq, Ord, Show, Read)让我们先看一下这种类型,然后再讨论好的部分。下面是PerfectlyBalancedTree Integer类型的几个典型值
Leaf 0
Branch (Leaf (0, 0))
Branch (Branch (Leaf ((0,0),(0,0))))
Branch (Branch (Branch (Leaf (((0,0),(0,0)),((0,0),(0,0))))))实际上,您可以将这种类型的任何值可视化为n个Branch标记的初始序列,后面是一个“我们终于完成了,谢天谢地”的Leaf标记,后面是包含的类型的2^n元组。凉爽的。
现在,我们将编写一个函数来解析一个稍微方便一些的表示。下面是几个调用示例:
*Main> :t fromString
fromString :: String -> PerfectlyBalancedTree Integer
*Main> fromString "0"
Leaf 0
*Main> fromString "b(42,69)"
Branch (Leaf (42,69))
*Main> fromString "bbb(((0,0),(0,0)),((0,0),(0,0)))"
Branch (Branch (Branch (Leaf (((0,0),(0,0)),((0,0),(0,0))))))在此过程中,编写一个稍微多一点的多态函数是很方便的。下面是:
fromString' :: Read a => String -> PerfectlyBalancedTree a
fromString' ('b':rest) = Branch (fromString' rest)
fromString' leaf = Leaf (read leaf)现在,我们真正的功能就是具有不同类型签名的相同功能:
fromString :: String -> PerfectlyBalancedTree Integer
fromString = fromString'但等一下..。刚才这里发生了什么?我在你身边滑倒了点东西!为什么我们不直接写这个?
fromStringNoGood :: String -> PerfectlyBalancedTree Integer
fromStringNoGood ('b':rest) = Branch (fromStringNoGood rest)
fromStringNoGood leaf = Leaf (read leaf)原因是在递归调用中,fromStringNoGood有一个不同的类型。它不是被调用返回一个PerfectlyBalancedTree Integer,而是被调用返回一个PerfectlyBalancedTree (Integer, Integer)。我们可以为自己写这样一个函数..。
fromStringStillNoGood :: String -> PerfectlyBalancedTree Integer
fromStringStillNoGood ('b':rest) = Branch (helper rest)
fromStringStillNoGood leaf = Leaf (read leaf)
helper :: String -> PerfectlyBalancedTree (Integer, Integer)
helper ('b':rest) = Branch ({- ... what goes here, now? -})
helper leaf = Leaf (read leaf)..。但是,这种方式存在着一个无限的回归,进入深度和深度嵌套类型的写作。
问题是,尽管我们对单纯顶级函数感兴趣,但我们仍然不能静态地确定在它使用的多态函数中调用什么类型的read!传递给我们的数据决定了应该返回哪种类型的元组read:String中更多的bs意味着一个更深层次的嵌套元组。
https://stackoverflow.com/questions/11420126
复制相似问题