Laz*_*535 3 haskell type-conversion
我正在经历"真实的世界Haskell",我正在做它随之而来的练习.
我注意到一些我觉得很奇怪的东西.
以此功能为例:
myAverage :: (Fractional a) => [a] -> Maybe a
myAverage [] = Nothing
myAverage xs = Just $ (mySum xs) / (fromIntegral $ myLength xs)
该(/)函数需要两个作为实例的参数Fractional.
myLength返回一个Int所以我使用the fromIntegral函数,因为我被告知.
但fromIntegral只保证返回的值将是一个实例Num.
为什么在这种情况下Num也"包含"一个实例Fractional.不是Fractional更具体吗?
为什么编译器不抱怨我只有一个Num来自返回类型而不是"正确" Fractional.
为什么我不能Int直接使用它,它也是一个实例Num,不是吗?
在打电话的情况下,mySum我得到它.它需要一个Nums 的列表,但我用Fractionals 列表(它们也是Nums,因为它们是从它派生的)提供它.返回类型具有相同的类型,从类型注释(见下文)可以看出:单个元素Fractional
但是如果fromIntegral我无法推断自己(编译器显然可以:-))返回的值也是一个实例Fractional.为什么?它所采用的类型显然不是Fractional.
整个功能按预期工作.
只是为了澄清:
mySum :: (Num a) => [a] -> a
myLength :: [a] -> Int
谢谢,
拉扎勒斯
sep*_*p2k 10
fromIntegral不产生一些我们只知道它是一个实例的未知类型Num.fromIntegral产生我们(通常含蓄地)要求它的任何类型,只要它的一个实例Num.
就OO语言而言,您需要将其视为泛型/模板,而不是虚拟继承/子类型多态.这是等价的Java签名fromIntegral会是什么样子<A extends Integral, B extends Num> B fromIntegral(A i),没有Num fromIntegral(Integral i).
所以,如果我们想要一个Int,我们得到一个Int.如果我们想要一个Integer,我们得到一个Integer.如果我们想要一个Double,我们得到一个Double.但是,如果我们想要一个String,我们运气不好,因为String它不是一个实例Num.
在这种情况下,我们希望awhere a是给定列表的元素类型.因此,如果我们传入一个Doubles 列表,fromIntegral给我们一个Double,如果我们传入一个Rationals 列表,fromIntegral给我们一个Rational.
你问:
但是,从整体来说只保证返回的值将是Num的一个实例.
这是真的,但请考虑以下类型fromIntegral:
fromIntegral :: (Integral a, Num b) => a -> b
Run Code Online (Sandbox Code Playgroud)
因此,fromIntegral允许我们将其转换Int为任何其他Num实例.
暂时,让我们处理具体类型而不是类型类.假设您已经定义myAverage如下:
myAverage :: [Double] -> Maybe Double
myAverage [] = Nothing
myAverage xs = Just $ mySum xs / (fromIntegral (myLength xs))
Run Code Online (Sandbox Code Playgroud)
Double支持除法,并fromIntegral能够将Int返回的转换myLength为a Double.
如果你使用了相同的定义将工作Rational代替Double,例如:
myAverage :: [Rational] -> Maybe Rational
Run Code Online (Sandbox Code Playgroud)
返回类型类及其类型检查方式:
myAverage :: Fractional a => [a] -> Maybe a
...
myAverage xs = Just $ mySum xs / (fromIntegral (myLength xs))
Run Code Online (Sandbox Code Playgroud)
这是怎么回事:
a是Fractional,而Fractional是Num的子类,所以a也是Num.xs有类型[a],所以mySum xs有类型amyLength xs 有类型 IntfromIntegral可以转换Int为任何其他Num实例,因此它可以转换Int为amySum xs而且fromIntegral表达式都有a一个类型,这是一个Fractional,所以我们可以执行除法.