用Python实现Haskell Heap,第1版
这是对Edward Z. Yang的Haskell Heap系列的翻译。
感谢Edward的无私奉献,允许我对这些文章进行翻译。
Edward以Creative Commons Attribution-ShareAlike 3.0 Unported License对文章进行了授权,所以译文也以此License发布。
---------------------------------------------------------------------------------
第一次看这个系列吗?那么请从头开始看。
下面是一个Haskell Heap的简单实现,它包含了目前为止我们讨论的Haskell Heap的全部内容:幽灵以及全部其他东西。
heap = {} # global # ---------------------------------------------------------------------# class Present(object): # Thunk def __init__(self, ghost): self.ghost = ghost # Ghost haunting the present self.opened = False # Evaluated? self.contents = None def open(self): if not self.opened: # Hey ghost! Give me your present! self.contents = self.ghost.disturb() self.opened = True self.ghost = None return self.contents class Ghost(object): # Code and closure def __init__(self, *args): self.tags = args # List of names of presents (closure) def disturb(self): raise NotImplemented class Inside(object): pass class GiftCard(Inside): # Constructor def __init__(self, name, *args): self.name = name # Name of gift card self.items = args # List of presents on heap you can redeem! def __str__(self): return " ".join([self.name] + map(str, self.items)) class Box(Inside): # Boxed, primitive data type def __init__(self, prim): self.prim = prim # Like an integer def __str__(self): return str(self.prim) # ---------------------------------------------------------------------# class IndirectionGhost(Ghost): def disturb(self): # Your present is in another castle! return heap[self.tags[0]].open() class AddingGhost(Ghost): def disturb(self): # Gotta make your gift, be back in a jiffy! item_1 = heap[self.tags[0]].open() item_2 = heap[self.tags[1]].open() result = item_1.prim + item_2.prim return Box(result) class UnsafePerformIOGhost(Ghost): def disturb(self): print "Fire ze missiles!" return heap[self.tags[0]].open() class PSeqGhost(Ghost): def disturb(self): heap[self.tags[0]].open() # Result ignored! return heap[self.tags[1]].open() class TraceGhost(Ghost): def disturb(self): print "Tracing %s" % self.tags[0] return heap[self.tags[0]].open() class ExplodingGhost(Ghost): def disturb(self): print "Boom!" raise Exception # ---------------------------------------------------------------------# def evaluate(tag): print "> evaluate %s" % tag heap[tag].open() def makeOpenPresent(x): present = Present(None) present.opened = True present.contents = x return present # Let's put some presents in the heap (since we can't make presents # of our own yet.) heap['bottom'] = Present(ExplodingGhost()) heap['io'] = Present(UnsafePerformIOGhost('just_1')) heap['just_1'] = makeOpenPresent(GiftCard('Just', 'bottom')) heap['1'] = makeOpenPresent(Box(1)) heap['2'] = makeOpenPresent(Box(2)) heap['3'] = makeOpenPresent(Box(3)) heap['traced_1']= Present(TraceGhost('1')) heap['traced_2']= Present(TraceGhost('2')) heap['traced_x']= Present(TraceGhost('x')) heap['x'] = Present(AddingGhost('traced_1', '3')) heap['y'] = Present(PSeqGhost('traced_2', 'x')) heap['z'] = Present(IndirectionGhost('traced_x')) print """$ cat src.hs import Debug.Trace import System.IO.Unsafe import Control.Parallel import Control.Exception bottom = error "Boom!" io = unsafePerformIO (putStrLn "Fire ze missiles" >> return (Just 1)) traced_1 = trace "Tracing 1" 1 traced_2 = trace "Tracing 2" 2 traced_x = trace "Tracing x" x x = traced_1 + 3 y = pseq traced_2 x z = traced_x main = do putStrLn "> evaluate 1" evaluate 1 putStrLn "> evaluate z" evaluate z putStrLn "> evaluate z" evaluate z putStrLn "> evaluate y" evaluate y putStrLn "> evaluate io" evaluate io putStrLn "> evaluate io" evaluate io putStrLn "> evaluate bottom" evaluate bottom $ runghc src.hs""" # Evaluating an already opened present doesn't do anything evaluate('1') # Evaluating an indirection ghost forces us to evaluate another present evaluate('z') # Once a present is opened, it stays opened evaluate('z') # Evaluating a pseq ghost may mean extra presents get opened evaluate('y') # unsafePerformIO can do anything, but maybe only once.. evaluate('io') evaluate('io') # Exploding presents may live in the heap, but they're only dangerous # if you evaluate them... evaluate('bottom')
技术注解:现在我们已经看到了ghost的Python实现,类似地,真正Core GHC的实现也就呼之欲出了。下面是一个pseq的例子:
x上的case操作对应于打开x,而一旦x打开,我们则做了指向y的间接引用(return heap['y'].open()),接下来是一个非多态添加ghost的例子:
下一个版本为了追求刺激我可能用C来写(还因为C版本可能更接近Haskell程序中真实的heap)。
上一篇:IO对Haskell Heap求值
下一篇:
pseq = \ (@ a) (@ b) (x :: a) (y :: b) -> case x of _ { __DEFAULT -> y }
x上的case操作对应于打开x,而一旦x打开,我们则做了指向y的间接引用(return heap['y'].open()),接下来是一个非多态添加ghost的例子:
add = \ (bx :: GHC.Types.Int) (by :: GHC.Types.Int) -> case bx of _ { GHC.Types.I# x -> case by of _ { GHC.Types.I# y -> GHC.Types.I# (GHC.Prim.+# x y) } }在上例中,Box扮演GHC.Types.I#的角色。看看你能不能找到其他的对应(bx和by上的模式匹配是什么?GHC.Prim.+#又是什么?)
下一个版本为了追求刺激我可能用C来写(还因为C版本可能更接近Haskell程序中真实的heap)。
上一篇:IO对Haskell Heap求值
下一篇: