【问题标题】:What does the UNPACK pragma do, in this case?在这种情况下,UNPACK 编译指示做什么?
【发布时间】:2016-02-29 03:46:02
【问题描述】:

我无法理解 UNPACK 在 Haskell 中的工作原理。 例如,考虑以下数据声明:

data P a b = P !a !b
data T = T {-# UNPACK #-} !(P Int Int)

如何解压数据类型T?会不会等价于

data T' = T' !Int !Int

或者Ints 是否会被进一步解包:

data T'' = T'' Int# Int#

?怎么样

data U = U {-# UNPACK #-} !(P Int (P Int Int))

?

【问题讨论】:

    标签: haskell indirection


    【解决方案1】:

    GHC documentation 描述 UNPACK 杂注如下:

    UNPACK 向编译器表明它应该将构造函数字段的内容解压缩到构造函数本身,从而移除一个间接级别。


    如何解压数据类型T

    data T = T (P Int Int)对应

    因此,data T = T {-# UNPACK #-} !(P Int Int) 对应

    简单地说,UNPACK 将构造函数 P 的内容解包到构造函数 T 的字段中,删除了一层间接和一个构造函数头 (P)。

    data T = T {-# UNPACK #-} !(P Int Int) 不像data T'' = T'' Int# Int# 那样“紧凑”:


    怎么样

    data U = U {-# UNPACK #-} !(P Int (P Int Int))
    

    ?

    同样,data U = U (P Int (P Int Int)) 对应

    data U = U {-# UNPACK #-} !(P Int (P Int Int))对应

    简而言之,UNPACK 将构造函数 P 的内容解压缩到构造函数 U 的字段中,删除了一级间接和一个构造函数头 (P)。

    资源

    【讨论】:

    • 那么,没有办法将T解包为T'',即去掉两级构造函数?
    • @Zeta 感谢您的编辑。你是如何制作这些漂亮的图表的?抖音? diagrams 库?
    • @Jubobs:我使用了dot aka GraphViz:digraph { node[shape=record]; con[label="U|<f0>"]; p[label="<p0>P|<p1>|<p2>"]; q[label="<q0>P|<q1>|<q2>"]; i1[label="<i1>I#|Int#"]; i2[label="<i2>I#|Int#"]; i3[label="<i3>I#|Int#"]; con:f0 -> p:p0 p:p1 -> i1:i1 p:p2 -> q:q0 q:q1 -> i2:i2 q:q2 -> i3:i3 }。并不是我所说的最佳实践 graphviz,但它确实起到了作用。
    • @Zeta 谢谢。
    • @AlexeyVagarenko 看来多态字段(例如P的数据声明中的ab)不能(yet?)解包。我可能是错的,但我不认为你可以解压缩 T 使其具有与 T'' 相同的内存占用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多