Nik*_*nov 0 polymorphism haskell types
例如,函数length抽象具体的sequence(Foldable),但不抽象具体的整数类型Int:
length :: Foldable t => t a -> Int
Run Code Online (Sandbox Code Playgroud)
拥有以下类型签名会更有用或更方便吗?
length' :: Foldable t, Integral i => t a -> i
Run Code Online (Sandbox Code Playgroud)
是的,或许首先要注意的是,更多的多态性并不总是一件好事.如果所有函数都具有高度多态的参数和结果,那么编译器几乎没有信息来启动类型推断,因此您最终必须键入更多笨拙的本地签名.
现在length,为什么你想要任何其他Integral类型的结果,但Int至少不是在64位机器上:
Word16通常不会在Haskell中提供很多性能或内存优势,因为会有一些拳击somwhere,然后你有一个只有16位信息的64位指针...有点傻.Int只保证29在某些极端情况下可以用尽,但实际上这仅适用于32位平台,无论如何在内存和性能方面都有所限制,因此您不希望处理如此庞大的数据.Foldable(由于参数化而总是装箱); 未装箱的矢量或ByteString表现更好.Integer或其他更昂贵的东西,不仅仅是因为长度而是因为上下文的原因,最好只计算长度Int并在结束时转换一次,而不是拖慢整个缓慢添加名单.也就是说,我确实有时希望签名实际上是实际存在的签名
genericlength :: (Foldable t, Num i) => t a -> i
Run Code Online (Sandbox Code Playgroud)
...注意,该函数不需要知道它的结果将是积分的.事实上,使结果合理化通常非常有用,所以我们可以随便写一下
average :: Fractional n => [n] -> n
average l = sum l / length l
Run Code Online (Sandbox Code Playgroud)
而不需要额外的fromIntegral.
原因不是这样的Prelude.length吗?我不知道,似乎颇具历史性.理由可能正如我在开始时所说的那样,你不需要太多的多态性.再说一遍,IMO通常最好将函数结果尽可能地变为多态,而是更严格地约束参数,因为这样结果总是会绑定到可以用于类型推断的东西.