诠释与常用词汇? [英] Int vs Word in common use?

查看:158
本文介绍了诠释与常用词汇?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是采取/返回 Int (即 ByteString.hGet Data.List.length )与使用强烈描述类型的Haskell模式相反,因为许多这些情况只能处理正数。使用 Word 会不会更好?还是有这些函数在 Int

解决方案

确实,Haskell类型系统的表现力鼓励用户为他们定义的实体指定精确的类型。然而,经验丰富的Haskellers会很快承认,必须在最终类型精度(除了在Haskell类型系统的当前限制下并不总能达到)和方便之间取得平衡。简而言之,精确的类型只对某一点有用。除此之外,他们往往只是造成额外的官僚主义,而没有多少收获。

让我们用一个例子来说明问题。考虑阶乘函数。对于大于1的所有 n n 的阶乘是偶数,1的阶乘不是非常有趣,让我们忽略那个。因此,为了确保我们在Haskell中的阶乘函数的实现是正确的,我们可能会试图引入一个新的数字类型,它只能表示无符号甚至整数:

 模块(偶数)其中

newtype Even = Even Integer

实例Num即使其中
...
fromInteger x | x`mod` 2 == 0 = Even x
|否则=错误不是偶数。

实例即使在
...
toInteger(偶数x)= x

我们在一个不导出构造函数的模块内部封装了这个数据类型,使其成为抽象的,并且使它成为所有相关类型类的一个实例 Int 是一个实例。现在我们可以给以下签名进行阶乘:

  factorial :: Int  - >甚至

factorial 肯定的类型更多比我们刚才说的返回 Int 要精确。但是你会发现用这种类型定义 factorial 真的很烦人,因为你需要乘法的一个版本来乘以(偶数或奇数) Int ,并带有 Even 并生成并且 Even 。更重要的是,您可能必须对客户端代码中的 factorial 调用的结果引入对 toInteger 的无关调用,这可能是一个重要的杂波和噪音来源,但收益甚微。此外,所有这些转换功能可能会对性能产生负面影响。另一个问题是,当引入一种新的,更精确的类型时,通常最终不得不复制各种图书馆功能。例如,如果你引入了非空列表类型 List1 a ,那么你将不得不重新实现 Data.List 已经提供,但仅用于 [a] 。当然,可以使用 ListLike 类型类的这些函数方法。但是你很快就会得到各种各样的adhoc类型类和其他样板,并且没有太多的收获。



最后一点是不应该考虑 Word Int 的无符号变体。 Haskell报告的实际大小为 Int 未指定,只能保证该类型能够表示整型[ - 2 29 ,2 29 - 1] 。据说 Word 类型提供了未指定宽度的无符号整数。不保证在任何符合的实现中, Word 的宽度对应于 Int 的宽度。



虽然我提出防止过度类型扩散的观点,但我确实承认引入一种 Natural 自然类型对人好点。然而,最终,除了 Int Integer 和Haskell之外,Haskell是否应该有自然数的专用类型各种各样的 Word * 类型,很大程度上是一种品味。而目前的状况可能只是历史事故的一大部分。

It seems like the common pattern of taking/returning Int (ie ByteString.hGet and Data.List.length) is contrary to the Haskell pattern of using strongly-descrbing types, since many of these cases can only handle positive numbers. Would it not be better to use Word, or is there a reason these functions are partial on Int?

解决方案

It is true that the expressiveness of the Haskell type system encourages users to assign precise types to entities they define. However, seasoned Haskellers will readily acknowledge that one must strike a balance between ultimate type precision (which besides isn't always attainable given the current limits of Haskell type system) and convenience. In short, precise types are only useful to a point. Beyond that point, they often just cause extra bureaucracy for little to no gain.

Let's illustrate the problem with an example. Consider the factorial function. For all n bigger than 1, the factorial of n is an even number, and the factorial of 1 isn't terribly interesting so let's ignore that one. Therefore, in order to make sure that our implementation of the factorial function in Haskell is correct, we might be tempted to introduce a new numeric type, that can only represent unsigned even integers:

module (Even) where

newtype Even = Even Integer

instance Num Even where
  ...
  fromInteger x | x `mod` 2 == 0 = Even x
                | otherwise = error "Not an even number."

instance Integral Even where
  ...
  toInteger (Even x) = x

We seal this datatype inside a module that doesn't export the constructor, to make it abstract, and make it an instance of the all the relevant type classes that Int is an instance of. Now we can give the following signature to factorial:

factorial :: Int -> Even

The type of factorial sure is more precise than if we just said that it returns Int. But you'll find that definining factorial with such a type is really quite annoying, because you need a version of multiplication that multiplies an (even or odd) Int with an Even and produces and Even. What's more, you might have to introduce extraneous calls to toInteger on the result of a call to factorial in client code, which can be a significant source of clutter and noise for little gain. Besides, all these conversion functions could potentially have a negative impact on performance.

Another problem is that when introducing a new, more precise type, you often end up having to duplicate all manner of library functions. For instance, if you introduce the type List1 a of non-empty lists, then you will have to reimplement many of the functions that Data.List already provides, but for [a] only. Sure, one can then make these functions methods of ListLike type class. But you quickly end up with all manner of adhoc type classes and other boilerplate, with again not much gain.

One final point is that one shouldn't consider Word to be an unsigned variant of Int. The Haskell report leaves the actual size of Int unspecified, and only guarantees that this type should be capable of representing integers in the range [− 229, 229 − 1]. The type Word is said to provide unsigned integers of unspecified width. It isn't guaranteed that in any conforming implementation the width of a Word corresponds to the width of an Int.

Though I make a point guarding against excessive type proliferation, I do acknowledge that introducing a type of Natural of naturals could be nice. Ultimately, though, whether Haskell should have a dedicated type for natural numbers, in addition to Int, Integer, and the various Word* types, is largely a matter of taste. And the current state of affairs is probably in very large part just an accident of history.

这篇关于诠释与常用词汇?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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