代码之家  ›  专栏  ›  技术社区  ›  Shersh

使用UnboxedSums定义的sum类型是否比普通枚举更有效?

  •  4
  • Shersh  · 技术社区  · 7 年前

    data Bool = False | True
    

    -XUnboxedSums 自GHC-8.2.1以来的扩展,允许以更高效的方式定义和类型。以下是文档中的引用:

    Bool -就像 (# (# #) | (# #) #)

    我想知道,这种表示是否比使用简单的纯Haskell enum数据类型更有效?

    1 回复  |  直到 7 年前
        1
  •  6
  •   jberryman    5 年前

    这两种类型不能互换使用。

    data Bool = False | True
    

    是提升式的。这意味着 x :: Bool 仍然可以不评估(例如,砰的一声)。因此,它将被表示为指针。

    (# (# #) | (# #) #)
    

    是unfted,并且实际上只能有这两个值,并且将仅表示为一个机器整数。

    空间效率

    不过,确实如此 意味着后者更节省空间:因为 True False 是空构造函数(不带参数),它们在程序的静态代码中一劳永逸地存在,指针只指向它们。所以成本在所有情况下都是一个机器字。

    运行时效率

    未装箱的变体可能比 Bool

    • 为了 布尔 ,首先要检查代码 这已经评估过了吗?

      分支非常有效:代码不必跟随指针:指针地址低位的指针标记将指示它是哪个构造函数。不过,屏蔽其他比特的成本很低。

    • 在未装箱的变体中,它只是 0 1

    有一天可能是真的

    杰伯里曼说 :截至2021年1月,以下内容似乎还没有实施,但这是有朝一日可能会发生的事情。

    在数据类型中取消装箱

    data Foo = Foo {-# UNPACK #-} !Bool
    

    你应该得到和你写的完全一样的结果

    data Foo = Foo (# (# #) | (# #) #)
    

    因为这是无界和扩展的主要目的。

    函数中的解装箱

    布尔 论点,例如。

    foo True = "Hello"
    foo False = "World!"
    

    然后我可以想象(但没有检查)编译器将其优化为 工人 (# (# #) | (# #) #) 和一个 那就搞定那张支票了。包装器可能会内联到 foo (# (# #) | (# #) #) .

    不用麻烦了。

    推荐文章