繁体   English   中英

为什么某些Haskell函数不抽象具体整数类型?

[英]Why some Haskell functions does not abstract concrete integral type?

例如,函数length抽象具体序列( Foldable ),但不抽象具体整数类型Int

length :: Foldable t => t a -> Int

具有以下类型签名会更有用或更方便吗?

length' :: Foldable t, Integral i => t a -> i

是的,也许吧,但是首先要注意的是,多态并不总是一件好事。 如果所有函数都具有高度多态的参数结果,则编译器几乎没有信息可以开始类型推断,因此最终您不得不键入更加尴尬的局部签名。

现在关于length ,几乎没有理由为什么想要除Int以外的任何其他Integral类型的结果,至少在64位计算机上不这样:

  • 诸如Word16类的较小类型在Haskell中通常不会提供太多的性能或内存优势,因为会有一些装箱操作,然后您只有一个64位的指针,只能指向16位的信息……有点傻。
  • 基本上不可能有一个列表(更不用说数组或映射)了,以至于它的长度无法用63位字来测量。 即使对于一个疯狂的懒惰列表,它在任何时候都不会完全存在于内存中。
    现在,严格来讲, Int仅保证在某些极端情况下可以用尽29,但实际上这仅与内存和性能受到限制的32位平台有关,因此您不希望处理如此大的数据。
  • 因此,应该优化性能穷竭性可能导致问题的任何应用程序,以使其比列表或其他Foldable (由于参数性而总是装箱)更有效。 未装箱的向量或ByteString的性能要好得多。
  • 如果您需要结果是Integer或其他更昂贵的东西,而不是因为长度而已,而不仅仅是出于上下文原因,那么最好以Int计算长度并在末尾进行一次转换,而不是将缓慢的加法运算拖累整个清单。

就是说,我确实有时希望签名实际上是已经存在的签名。

genericlength :: (Foldable t, Num i) => t a -> i

...请注意,该函数不需要知道其结果将是整数。 实际上,使结果合理是非常有用的,因此我们可以编写

average :: Fractional n => [n] -> n
average l = sum l / length l

而不需要额外的fromIntegral

Prelude.length不是这样的Prelude.length 我不知道,似乎颇有历史。 理由可能就像我一开始所说的那样,你不想过多的多态性 再说一次,IMO通常是使函数结果尽可能多态的,并且更严格地限制参数是一个好主意,因为这样,结果将始终绑定到可以用于类型推断的对象上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM