Haskell是否有返回类型重载? [英] Does Haskell have return type overloading?

查看:84
本文介绍了Haskell是否有返回类型重载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于我读到的关于Haskell的内容,以及我用GHC所做的实验,Haskell似乎有返回类型重载(又名ad hoc多态)。其中一个例子是 fromInteger 函数,它可以给你一个 Double 或者一个 Integer 取决于结果的使用位置。例如:

  fd :: Double  - >字符串
fd x =Double

fi :: Integer - >字符串
fi x =整数

fd(fromInteger 5) - 返回Double
fi(fromInteger 5) - 返回Integer

Haskell的一个简洁的介绍似乎同意这个说法:


我们所说的多态性目前为止通常称为参数多态性。还有另一种叫做ad hoc多态的,更好的称为重载。这里有一些特殊的多态性的例子:


  • 文字1,2等通常用于表示固定和任意的精度整数。

如果数字文字被认为是ad hoc多态性的一个例子(又称重载) ,那么似乎对于像 fromInteger 这样的函数的结果也是如此。实际上,我已经找到了堆栈溢出的其他问题的一些答案,这些答案表明Haskell有重载不过,至少有一位Haskell程序员告诉我这不是返回类型重载,而是一个参数多态性的例子,其中参数被一个通用量词绑定。



我认为他得到的是 fromInteger 正在返回a来自每个 Num (某种不确定类型)的实例的值。



这似乎是一个合理的解释,但就我所知,Haskell从来没有让我们看到这些实例值中的多个(部分归功于单态限制)。它也似乎是我们看待的实际情况,可以静态确定。因为所有这一切,在表达式中 fd(fromInteger 5)来自整数5的子表达式 看起来是合理的。类型 Double ,而在表达式 fi(fromInteger 5)中,来自整数5的子表达式 类型是 Integer



那么,Haskell是否有返回类型重载? / p>

如果不是,请提供以下示例之一:


  • 有效如果Haskell具有返回类型重载,那么Haskell代码将具有不同的行为

  • 有效的Haskell代码如果Haskell具有返回类型重载,则该代码无效

  • 无效Haskell如果Haskell有返回类型重载,那么这个代码是有效的
  • 那就是Haskell将你正在考虑的返回类型多态转化为参数多态类型类的字典传递转换。 (尽管这不是实现类型类或关于它们的原因的唯一方法,但它只是最受欢迎的。)



    基本上来自 code>在Haskell中有这种类型:

      fromInteger :: Num a =>整数 - > a 

    这可能会被内部翻译成这样的内容:

      fromInteger#:: NumDictionary#a  - >整数 - > a 
    fromInteger#NumDictionary#{fromInteger = method} x = method x

    data NumDictionary#a = NumDictionary#{...
    ,fromInteger :: Integer - > a
    ,...}

    因此,对于每个具体类型 Num 实例中,有一个 NumDictionary#T 值,它包含一个函数 fromInteger :: Integer - > T ,并且所有使用 Num 类型类的代码都被转换成以字典作为参数的代码。


    Based on what I've read about Haskell, and the experimentation I've done with GHC, it seems like Haskell has return type overloading (aka ad hoc polymorphism). One example of this is the fromInteger function which can give you a Double or an Integer depending on where the result is used. For example:

    fd :: Double -> String
    fd x = "Double"
    
    fi :: Integer -> String
    fi x = "Integer"
    
    fd (fromInteger 5)  -- returns "Double"
    fi (fromInteger 5)  -- returns "Integer"
    

    A Gentle Introduction to Haskell seems to agree with this when it says:

    The kind of polymorphism that we have talked about so far is commonly called parametric polymorphism. There is another kind called ad hoc polymorphism, better known as overloading. Here are some examples of ad hoc polymorphism:

    • The literals 1, 2, etc. are often used to represent both fixed and arbitrary precision integers.

    If the numeric literals are considered to be an example of ad hoc polymorphism (aka overloading), then it seems that the same is true for the result of functions like fromInteger.

    And in fact, I've found some answers to other questions on Stack Overflow that suggest that Haskell has overloading by return type.

    However, at least one Haskell programmer has told me that this isn't return type overloading, and is instead an example of "parametric polymorphism, where the parameter is bound by a universal quantifier".

    I think what he's getting at is that fromInteger is returning a value from every instance of Num (sort of a nondeterministic type).

    That seems like a reasonable interpretation, but as far as I can tell, Haskell never lets us look at more than one of these instance values (thanks in part to the Monomorphism restriction). It also seems like the actual instance who's value we look at can be determined statically. Because of all of this, it seems reasonable to say that in the expression fd (fromInteger 5) the subexpression fromInteger 5 is of type Double, while in the expression fi (fromInteger 5) the subexpression fromInteger 5 is of type Integer.

    So, does Haskell have return type overloading?

    If not, please provide an example of one of the following:

    • valid Haskell code that would have different behavior if Haskell had return type overloading
    • valid Haskell code that would be invalid if Haskell had return type overloading
    • invalid Haskell code that would be valid if Haskell had return type overloading

    解决方案

    Well, one way to look at it is that Haskell translates the return type polymorphism that you're thinking of into parametric polymorphism, using something called the dictionary-passing translation for type classes. (Though this is not the only way to implement type classes or reason about them; it's just the most popular.)

    Basically, fromInteger has this type in Haskell:

    fromInteger :: Num a => Integer -> a
    

    That might be translated internally into something like this:

    fromInteger# :: NumDictionary# a -> Integer -> a
    fromInteger# NumDictionary# { fromInteger = method } x = method x
    
    data NumDictionary# a = NumDictionary# { ...
                                           , fromInteger :: Integer -> a
                                           , ... }
    

    So for each concrete type T with a Num instance, there's a NumDictionary# T value that contains a function fromInteger :: Integer -> T, and all code that uses the Num type class is translated into code that takes a dictionary as the argument.

    这篇关于Haskell是否有返回类型重载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆