什么是库中的哈希(#)来源?

Car*_*ate 16 haskell

我试图弄清楚mVars是如何工作的,我偶然发现了这段代码:

-- |Create an 'MVar' which is initially empty.
newEmptyMVar  :: IO (MVar a)
newEmptyMVar = IO $ \ s# ->
    case newMVar# s# of
         (# s2#, svar# #) -> (# s2#, MVar svar# #)
Run Code Online (Sandbox Code Playgroud)

除了混淆地相互递归之外newMVar,它还充满了哈希(#).

在两者之间,我无法弄清楚它是如何工作的.我知道这基本上只是mVar的伪构造函数,但模块的其余部分(实际上大部分库)都包含它们,我找不到它们.谷歌搜索"Haskell哈希"并没有产生任何相关的东西.

Dan*_*zer 19

他们(字面上)是魔法哈希.它们区分GHC的原语,如添加,未装箱类型和未装箱的元组.你可以用它来编写它们

{-# LANGUAGE MagicHash #-}
Run Code Online (Sandbox Code Playgroud)

现在您可以导入允许您使用它们的存根

import GHC.Exts

unboxed :: Int# -> Int# -> Int#
unboxed a# b# = a# +# b#

boxed :: Int -> Int -> Int
boxed (I# a#) (I# b#) = I# (unboxed a# b#)
Run Code Online (Sandbox Code Playgroud)

当你想到它时,这实际上有点漂亮,通过包装像这样的神奇和严格的原语,我们可以在运行时系统级别统一处理惰性IntChars.

因为原语不是盒装的,所以它们在种类层面上是分开的.这意味着Int#没有*像普通类型那样的东西,这也意味着类似的东西

kindClash :: Int# -> Int#
kindClash = id -- id expects boxed types
Run Code Online (Sandbox Code Playgroud)

不会编译.

要进一步详细说明您的代码,newMVar请在GHC中调用编译器原语以分配新的可变变量.与编译器调用的瘦包装器不同,它不是相互递归的.因为我们把它IO视为一个反常状态的monad,所以在这个函数的角落也有一些黑暗聚集,但是我们不要密切关注它.我非常喜欢我的理智.

我不会在日常代码中使用原语,也不应该使用原语.它们在实现疯狂优化热点时出现,或者接近原始抽象,例如您正在查看的内容.

  • @Carcigenicate,`newMVar`和`newMVar #`是*不同的函数*.`newEmptyMVar`调用`newMVar #`,而不是`newMVar`.至于包装器,基本上有一个primop,`newMVar #`,然后是一个小包装函数`newEmptyMVar`,它可以进行装箱和拆箱,并调用底层的primop`newMVar #`来完成真正的工作. (2认同)