gpt4 book ai didi

haskell - dataToTag 参数的严格性

转载 作者:行者123 更新时间:2023-12-02 05:57:49 24 4
gpt4 key购买 nike

GHC.Prim中,我们发现了一个名为dataToTag#的神奇函数。 :

dataToTag# :: a -> Int#

它根据它使用的数据构造函数将任何类型的值转换为整数。这用于加速 EqOrdEnum 的派生实现。在 GHC 源中,docs for dataToTag#解释该参数应该已经被评估:

The dataToTag# primop should always be applied to an evaluated argument. The way to ensure this is to invoke it via the 'getTag' wrapper in GHC.Base:

getTag :: a -> Int#
getTag !x = dataToTag# x

对我来说,我们需要在调用 dataToTag# 之前强制 x 进行评估,这对我来说是完全有意义的。我不明白的是为什么刘海图案就足够了。 getTag 的定义只是语法糖:

getTag :: a -> Int#
getTag x = x `seq` dataToTag# x

但是让我们转向 docs for seq :

A note on evaluation order: the expression seq a b does not guarantee that a will be evaluated before b. The only guarantee given by seq is that the both a and b will be evaluated before seq returns a value. In particular, this means that b may be evaluated before a. If you need to guarantee a specific order of evaluation, you must use the function pseq from the "parallel" package.

parallel 包的 Control.Parallel 模块中,文档 elaborate further :

... seq is strict in both its arguments, so the compiler may, for example, rearrange a `seq` b into b `seq` a `seq` b ...

考虑到 seq 不足以控制计算顺序,如何保证 getTag 正常工作?

最佳答案

GHC 跟踪有关每个 primop 的某些信息。一个关键数据是primop是否“can_fail”。该标志的原始含义是,如果 primop 可能导致硬故障,则它可能会失败。例如,如果索引超出范围,数组索引可能会导致段错误,因此索引操作可能会失败。

如果 primop 可能失败,GHC 将限制它周围的某些转换,特别是不会将其从任何 case 表达式中 float 。例如,如果

if n < bound
then unsafeIndex c n
else error "out of range"

编译为

case unsafeIndex v n of
!x -> if n < bound
then x
else error "out of range"

其中一个底部是异常(exception);另一个是段错误。

dataToTag# 被标记为 can_fail。所以 GHC 看到(在 Core 中)类似

getTag = \x -> case x of
y -> dataToTag# y

(注意case在Core中是严格的。)因为dataToTag#被标记为can_fail,所以它不会从任何case中 float 出来> 表达式。

关于haskell - dataToTag 参数的严格性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45043009/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com