什么是Addr#类型,我该如何使用它?

AJF*_*mar 3 haskell primitive-types

我最近一直在寻找各种Haskell怪癖,比如当我发现这种Addr#类型时的未装箱类型和诸如此类的东西.

GHC.Prim包描述如下:

假定任意机器地址指向垃圾收集堆之外.

这对我来说意义不大.

此外,我一直在寻找使用类型的函数:

readIntOffAddr# :: Addr# -> Int# -> State# s -> (#State# s, Int##)
Run Code Online (Sandbox Code Playgroud)

这是什么类型的?我该怎么办?为什么有必要?

Rei*_*ton 8

作为迈克尔答案的补充:

Addr#是一个未装箱的类型,它的底层Ptr a方式Int#与底层的未装箱类型相同Int.其内容可能被解释为机器地址,但就编译器和GC而言,它只是另一种整数类型(无论系统中的大小指针是什么).因为它是一个任意的机器地址而不是GC管理的指针,所以它应该不会指向Haskell堆,因为Haskell堆对象的地址从Haskell级别看是不稳定的(GC可能在任何一点发生)你的程序,然后你Addr#现在所指向的任何对象都存在于其他地方,或者根本没有.

通常,Ptr a/ Addr#将包含从malloc/ mmapetc 返回的指针,或指向C全局变量的指针,或者通常指针可能在C程序中明显指向的任何类型的事物.通常readIntOffAddr#在与C函数接口时使用,该函数返回或修改传递的内容HsInt *.(好吧,你不会直接使用它,你会使用我认为实现IntpeekElemOff Storable方法readIntOffAddr#,或者你会使用更高级别的函数peekArray).


Mic*_*ael 7

等效的*C代码将是:

long readIntOffAddr(long *ptr, long offset) {
    return ptr[offset];
}
Run Code Online (Sandbox Code Playgroud)

Addr#就像void *.该函数具有类似IO签名,因为它不是"纯粹的".对函数的多次调用可能会返回不同的值(显然).

*更新(2018):我刚刚了解到将C int类型与Haskells Int#类型等同是错误的.所以我改变int,以long在上面的代码片断.这也(可能)不是100%正确,但至少对于我所见过的所有GHC实现都是如此.在GHC版本6-8(尚未检查其他版本)中,Int#在32位平台上为32位宽,在64位平台上为64位宽.这与long我所知道的32位和64位平台上所有C/C++实现的GCC行为相匹配,所以我认为等同Int#long是一个很好的第一近似值.在过去3年中没有人注意到这种轻微的不准确性(或者足以编辑/评论),所以请不要为此向我投降.我怀疑是否有任何Haskell/Platform/C组合在哪里HsInt!= longHaskell实现有一个readIntOffAddr#功能..请证明我错了.

  • 是的,我只是说'IO`-like,因为整个`IO`-monad是围绕传递`State#`值的概念而构建的.如果你看一下GHC中`IO` monad的实现,你会发现它被定义为`newtype IO a = IO(State#RealWorld - >(#State#RealWorld,a#))`其中右边 - 手边`State#RealWorld - >(#State#RealWorld,##)`看起来非常类似于`State#s - >(#State#s,a#)`.因此,`readIntOffAddr #`函数可以很容易地被提升到`IO` monad. (2认同)