最終的にはghc-prim を使用してクロージャを検査するためのghci 実装。:sprint
これをヒープ オブジェクトunpackClosure#
の形式の知識と組み合わせて、クロージャが弱いヘッドの正規形まで評価されたかどうかを判断できます。
の ghci 実装によって行われた検査を再現するには、いくつかの方法があります:sprint
。GHC api は で公開さgetClosureData :: DynFlags -> a -> IO Closure
れRtClosureInspect
ます。ghc- primのみに依存するバキューム パッケージは、からのコードを再現し、 . たとえば、これらの表現のいずれかを調べる方法は、すぐには明らかではありません。ghc-heap-viewパッケージはクロージャを検査し、と の詳細ビューの両方を公開します。ghc-heap-view は GHC api に依存します。RtClosureInspect
getClosure :: a -> IO Closure
Closure
getClosureData :: a -> IO Closure
Closure
from ghc-heap-view の観点からevaluated
書くことができます。getBoxedClosureData
import GHC.HeapView
evaluated :: a -> IO Bool
evaluated = go . asBox
where
go box = do
c <- getBoxedClosureData box
case c of
ThunkClosure {} -> return False
SelectorClosure {} -> return False
APClosure {} -> return False
APStackClosure {} -> return False
IndClosure {indirectee = b'} -> go b'
BlackholeClosure {indirectee = b'} -> go b'
_ -> return True
このブラックホール クロージャの処理は、ブラックホールが評価されている間は正しくない可能性があります。セレクタ クロージャの処理が正しくない可能性があります。AP クロージャが弱い頭の正規形ではないという仮定は、正しくない可能性があります。他のすべてのクロージャーが WHNF にあるという仮定は、ほぼ確実に正しくありません。
例
この例では、一方のスレッドが式を評価していることを他方のスレッドで観察するために、2 つの同時スレッドが必要です。
import Data.Char
import Control.Concurrent
unsafe
評価を選択的に強制することで、何も頼ることなく、関数から横方向に情報を伝達できます。以下は、ペアの一方または他方を強制することを選択できるサンクのペアのストリームを構築します。
mkBitStream :: Integer -> [(Integer, Integer)]
mkBitStream a = (a+2, a+3) : mkBitStream (a+1)
zero
最初のものをone
強制し、2番目のものを強制します。
zero :: [(x, y)] -> [(x, y)]
zero ((x, _):t) = x `seq` t
one :: [(x, y)] -> [(x, y)]
one ((_, y):t) = y `seq` t
copy
は、データの検査に基づいてストリーム内のビットを強制するという副作用を持つ悪のアイデンティティ関数です。
copy :: (a -> Bool) -> [(x, y)] -> [a] -> [a]
copy f bs [] = []
copy f bs (x:xs) = let bs' = if f x then one bs else zero bs
in bs' `seq` (x:copy f bs' xs)
readBs
ペアの各サンクがevaluated
.
readBs :: [(x, y)] -> IO ()
readBs bs@((f, t):bs') = do
f' <- evaluated f
if f'
then putStrLn "0" >> readBs bs'
else do
t' <- evaluated t
if t'
then putStrLn "1" >> readBs bs'
else readBs bs
印刷時に強制copy
すると、読み取った文字列について観察された情報が印刷されるという副作用があります。
main = do
let bs = mkBitStream 0
forkIO (readBs bs)
text <- getLine
putStrLn (copy isAlpha bs text)
getLine
プログラムを実行して入力abc123
を提供すると、各文字がisAlpha
abc123
abc123
1
1
1
0
0
0