Haskell 地址类型是什么?我如何使用它?
当我发现Haskell 地址类型是什么?我如何使用它?,haskell,primitive-types,Haskell,Primitive Types,当我发现Addr#类型时,我最近一直在研究各种Haskell怪癖,比如unbox类型等等 该文件包对其进行了如下描述: 假定指向垃圾收集堆外部的任意计算机地址 这对我来说意义不大 此外,我一直在寻找使用以下类型的函数: readIntOffAddr# :: Addr# -> Int# -> State# s -> (#State# s, Int##) 这是什么类型的?我能用它做什么?为什么必须这样做?等效的*C代码是: long readIntOffAddr(long *pt
Addr#
类型时,我最近一直在研究各种Haskell怪癖,比如unbox类型等等
该文件包对其进行了如下描述:
假定指向垃圾收集堆外部的任意计算机地址
这对我来说意义不大
此外,我一直在寻找使用以下类型的函数:
readIntOffAddr# :: Addr# -> Int# -> State# s -> (#State# s, Int##)
这是什么类型的?我能用它做什么?为什么必须这样做?等效的*C代码是:
long readIntOffAddr(long *ptr, long offset) {
return ptr[offset];
}
Addr#
就像void*
。该函数具有类似于IO的签名,因为它不是“纯的”。对函数的多次调用可能会返回不同的值(显然)
*更新(2018):我刚刚了解到,将C的
int
类型等同于Haskell的int 35;
类型是错误的。因此,我在上面的代码片段中将int
更改为long
。这也(可能)不是100%正确,但至少我所看到的所有GHC实现都是如此。在GHC版本6-8中(未检查其他版本),Int#
在32位平台上为32位宽,在64位平台上为64位宽。这与我所知道的所有32位和64位平台上的C/C++实现的long
的GCC行为相匹配,因此我认为将Int
等同于long
是一个很好的第一近似值。在过去的3年里,没有人注意到这个微小的错误(或者非常关心编辑/评论),所以请不要因为这个而投我的反对票。我怀疑有任何Haskell/Platform/C组合,其中HsInt
!=long
其中Haskell实现具有一个readintofaddr 35;
函数。。请证明我错了。作为对Michael答案的补充:
Addr#
是Ptr a
下的未装箱类型,其方式与Int#
是Int
下的未装箱类型相同。它的内容可能被解释为一个机器地址,尽管就编译器和GC而言,它只是另一个整数类型(不管系统上的指针大小如何)。因为它是一个任意的机器地址,而不是GC管理的指针,所以它不应该指向Haskell堆,因为从Haskell级别来看,Haskell堆对象的地址并不稳定(GC可能发生在程序中的任何一点,然后您指向的Addr#
的任何对象现在都位于其他地方,或者根本不存在)
通常一个
ptra
/Addr#
将包含一个从malloc
/mmap
/等返回的指针,或者一个指向C全局变量的指针,或者通常是指针可能在C程序中敏感地指向的任何类型的东西。当与一个C函数接口时,通常使用readintofaddr
返回或修改已传递的HsInt*
的内容(好吧,您不会直接使用它,而是使用Int
的peekElemOff
Storable
方法,我假定该方法是根据readintofaddr.
实现的,或者您会使用更高级别的函数,如peekArray
)是的,我只说了IO
-like,因为整个IO
-monad是围绕着传递State
值的概念构建的。如果你看一下GHC中IO
monad的实现,你会发现它被定义为newtypeioa=IO(State#RealWorld->(#State#RealWorld#RealWorld,a#))
右边的State#RealWorld->(#State#RealWorld,a#)
看起来与State#s->(#State#s,a#)非常相似。
因此,readintodrra#
函数可以轻松地提升到IO
单子。这为我澄清了这一点。谢谢。