如何在 Haskell 中操作未装箱的类型

Dan*_*kov 3 haskell ghc

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

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

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

  boxInt :: Int# -> Int
  unboxInt :: Int -> Int#
Run Code Online (Sandbox Code Playgroud)

实例 Show Int# 和实例 Read Int# 不能存在,因为显示和读取是多态的。

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

HTN*_*TNW 5

IntFloat等只是dataGHC 中的类型:

data Int = I# Int#
data Float = F# Float#
-- etc.
Run Code Online (Sandbox Code Playgroud)

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

{-# LANGUAGE MagicHash #-}

import GHC.Exts

main = do I# x <- readLn
          I# y <- readLn
          print (I# (x +# y))
Run Code Online (Sandbox Code Playgroud)

  • @DaneelS.Yaitskov 因为你不需要自己处理未装箱的原始类型。看我的回答。 (2认同)

lef*_*out 5

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

尽管这在某种意义上是正确的,但您通常不必担心。GHC 非常努力地优化内置类型的框,并且我希望它在大多数情况下都能做得很好,您也可以手动执行此操作。

在实践中,你应该更加小心的是确保

  • 它实际上看到了它知道未装箱形式的具体Int或类型。Float特别是,这对于多态函数不起作用(多态性通常依赖于框,就像在 OO 语言中一样)。
    如果您希望函数是多态的并且仍然可以使用基本类型快速运行,请确保添加SPECIALIZE注释和/或重写规则。
  • 懒惰不会成为障碍。未装箱的类型始终是严格的,因此严格注释可以使 GHC 更轻松地删除装箱。

当然,还要分析您的代码。

仅当您确实确定需要它时(例如,确保当新的 GHC 以不同方式优化时,这些框不会重新出现),或者如果您想获取 SIMD 指令,您实际上应该手动执行访问未装箱的原始类型。