【问题标题】:How to operate with unboxed types in Haskell如何在 Haskell 中使用未装箱的类型
【发布时间】:2020-04-17 01:38:56
【问题描述】:

有 Int、Float 等的未装箱类型 GHC。 我知道基于它们构建的代码运行开销更少, 但我看不到如何根据未装箱的 Int 向/从函数输入和输出数据的方法,即

GHC.Exts 定义了函数 (+#) 和 (*#),但我找不到函数装箱/拆箱

  readInt:: String -> Int#
  showInt:: Int# -> String

  boxInt :: Int# -> Int
  unboxInt :: Int -> Int#

instance Show Int# 和 instance Read Int# 不能存在,因为 show 和 read 是多态的。

如果没有这些功能,我如何将未装箱类型的优化代码块与应用程序的其余部分集成?

【问题讨论】:

    标签: haskell ghc


    【解决方案1】:

    IntFloat 等只是 GHC 中的data 类型:

    data Int = I# Int#
    data Float = F# Float#
    -- etc.
    

    构造函数仅由GHC.Exts 导出。导入它并使用构造函数进行转换:

    {-# LANGUAGE MagicHash #-}
    
    import GHC.Exts
    
    main = do I# x <- readLn
              I# y <- readLn
              print (I# (x +# y))
    

    【讨论】:

    • 如果这么简单,为什么 GHC.Prim 模块没有定义 Int -> Int# 和返回的辅助方法?
    • “返回”方法确实存在:I# 本身。
    • @DaneelS.Yaitskov 因为您不应该自己处理未装箱的原始类型。看我的回答。
    【解决方案2】:

    我知道基于它们构建的代码运行开销更少

    虽然从某种意义上说这是对的,但您通常不必担心。 GHC 非常努力地优化掉内置类型的盒子,我希望它在大多数情况下都能很好地做到这一点,而您也可以手动完成。

    在实践中,你更应该注意的是确保

    • 它实际上看到了具体的IntFloat 类型,它知道它的未装箱形式。特别是,这适用于多态函数(多态通常依赖于框,就像它在 OO 语言中所做的那样)。
      如果您希望函数是多态的并且仍然使用原始类型,请确保添加 SPECIALIZE 注释和/或重写规则。
    • 懒惰不会妨碍你。未装箱的类型始终是严格的,因此严格性注释可以让 GHC 更轻松地移除这些盒子。

    当然还有分析你的代码。

    只有当你真的确定你想要它时(例如,确保在优化不同的新 GHC 时这些框不会重新出现),或者如果你想获取 SIMD 指令,如果您真的手动访问未装箱的原始类型。

    【讨论】:

      猜你喜欢
      • 2012-12-14
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      • 1970-01-01
      相关资源
      最近更新 更多