Haskell 为度量数据结构的函数指定什么类型?整数,整数,整数?
我有一个数据结构,比如表达式树或图。我想添加一些“测量”功能,例如Haskell 为度量数据结构的函数指定什么类型?整数,整数,整数?,haskell,Haskell,我有一个数据结构,比如表达式树或图。我想添加一些“测量”功能,例如深度和大小 如何最好地键入这些函数 我认为以下三种变体的作用大致相同: depth::Expr->Int depth::Expr->Integer depth::Num a=>Expr->a 我有以下考虑: 我以base和fgl为例,它们一贯使用Int,但使用数据。List还具有genericlelength等返回类型多态的函数,我在想,也许这些通用函数的增加反映了一种现代化趋势,我可能应该尊重和加强这一趋势 在一些广泛使用
深度
和大小
如何最好地键入这些函数
我认为以下三种变体的作用大致相同:
depth::Expr->Int
depth::Expr->Integer
depth::Num a=>Expr->a
- 我以
和base
为例,它们一贯使用fgl
,但使用Int
还具有数据。List
等返回类型多态的函数,我在想,也许这些通用函数的增加反映了一种现代化趋势,我可能应该尊重和加强这一趋势genericlelength
- 在一些广泛使用的库中,当用户需要返回类型的多个可能选择时,可以看到类似的思想运动,这些库提供具有相同功能的综合功能集(例如,
提供的解析器既可以接受惰性的,也可以接受严格类型的xml管道
或ByteString
)文本
是一种比Integer
更好的类型,有时我发现我需要将列表的长度转换为Int
整数,比如说,因为在
中运行的算法需要考虑这个长度Integer
- 使函数返回
意味着这些函数是多态的,可能会有性能损失。我不太清楚所有细节,但据我所知,可能会有一些运行时成本,多态的东西更难记忆Integral
什么是公认的最佳实践?哪一部分是由于遗留和兼容性考虑?(即,如果
Data.List
是今天设计的,那么length
等函数会有什么类型?)我错过了任何优点和缺点吗?简短的回答:通常使用Int
,如果需要将其转换为其他内容,请使用fromIntegral
(如果您发现自己经常进行转换,请定义fi=fromIntegral
以保存键入内容,或者创建自己的包装器。)
主要考虑的是性能。您希望编写算法,以便在内部使用有效的整数类型。前提是Int
对于您正在进行的任何计算都足够大(标准保证有符号30位整数,但即使在使用GHC的32位平台上,它也是有符号32位整数),您可以假设它将是平台上的高速整数类型,特别是与integer
相比(它具有无法优化的装箱和bignum计算开销)。请注意,性能差异可能很大。使用Int
s与Integer
s相比,简单的计数算法通常会快5-10倍
虽然您可以为您的函数提供不同的签名:
depth :: Expr -> Integer
depth :: (Num a) => Expr -> a
但实际上,使用高效的Int
类型在引擎盖下实现它,并在最后进行转换,使转换隐式让我觉得这是一个糟糕的做法。特别是如果这是一个库函数,那么让我感觉更为敏感的是,通过使其成为签名的一部分,可以清楚地表明Int
正在内部使用e
关于您列出的注意事项:
首先,Data.List
中的generic*
函数并不现代。特别是,genericlelength
于1996年7月发布。在此之前,length
已根据genericlelength
定义为:
length :: [a] -> Int
length = genericLength
但在GHC 0.29中,这一定义被注释为#ifdef USE_REPORT_PRELUDE
,几个手动优化的长度变量独立定义。其他通用*
函数不在0.29中,但GHC 4.02(1998年)已经存在
最重要的是,当Prelude
版本的length
从列表推广到Foldable
s,这是一个相当新的发展(自GHC 7.10?)时,没有人关心如何使用genericlelength
。我也不认为“在野外”使用过这些函数在任何严肃的Haskell代码中。在大多数情况下,您可以认为它们已被弃用
其次,在库中使用lazy/strict和ByteString
/Text
变体代表了一种不同的情况。特别是,管道xml
用户通常会根据考虑在lazy和strict变体之间以及ByteString
和Text
类型之间做出决定关于正在处理的数据和算法的构造,这些算法影响深远,并渗透到给定程序的整个类型系统中。如果将导管xml
与惰性文本
类型一起使用的唯一方法是将其逐段转换为严格的ByteString
s,则将其传递给库,然后将其从d将其转换回惰性文本类型,没有人会接受这种复杂性。相反,基于单态Int
的深度定义可以很好地工作,因为您只需要fromInteger.depth
将其适应任何数字上下文
第三,如上所述,Integer
只是一种“更好”的类型,因为在您不关心性能的情况下,它具有任意精度。对于任何实际设置中的depth
和count
等内容,性能可能比无限精度更重要
第四,我不认为e
data Integer = SmallInteger Int | LargeInteger ByteArray