2014-10-02 110 views
16

我試圖找出mVars如何工作的,我碰到此位的代碼來:什麼是哈希(#)用於圖書館的來源?

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

除了是容易混淆與newMVar相互遞歸,它也散落着hashs(#)。

在這兩者之間,我無法弄清楚它是如何工作的。我知道這基本上只是mVar的一個僞構造函數,但模塊的其餘部分(實際上大部分庫)都包含它們,並且我無法找到它們。谷歌搜索「哈斯克爾哈希」沒有產生任何相關。

回答

18

他們是(字面上)魔法哈希值。他們區分GHC的基元,如添加,取消裝箱類型和取消裝箱的元組。你能使用

{-# LANGUAGE MagicHash #-} 

寫他們,現在您可以通過包裝的神奇和嚴格的原語import,讓你使用他們

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#) 

這其實是有點漂亮,當你想想看存根像這樣,我們可以在運行時系統級統一處理懶惰IntChar

因爲原語沒有裝箱,所以它們在類別層次上分開。這意味着,Int#沒有那種*像正常的類型,這也意味着像

kindClash :: Int# -> Int# 
kindClash = id -- id expects boxed types 

不會編譯。

爲了進一步闡述你的代碼,newMVar包括一個調用GHC中的編譯器原語來分配一個新的可變變量。它不像編譯器調用的簡單包裝那樣相互遞歸。由於我們將IO視爲不正常的狀態monad,因此在這個函數的角落也會出現一些黑暗,但我們不要緊盯這個。我太喜歡我的理智了。

我不在日常代碼中使用原語,也不應該。他們在實現瘋狂優化的熱點時,或者接近原始抽象時出現,比如你在看什麼。

+0

謝謝。因此,爲了理解庫的片段,我基本上可以忽略它們,只是想想它們與之相關的類型? – Carcigenicate 2014-10-02 21:53:55

+1

@Carcigenicate很多,是的。 – bheklilr 2014-10-02 21:55:57

+0

@Carcigenicate我會這麼說,如果你真的好奇,你可以閱讀原始文檔,但是我不認爲你會從他們那裏獲得很多。 – jozefg 2014-10-02 21:56:27