2016-11-28 37 views
7

GHC 8, GHC.Stack modülünden HasCallStack modülünü sağlar; bu sayede işlevler istendiğinde bir yığın çerçevesinin kaydedilmesini isteyebilir. Ayrıca çağrı yığınını “donduran” withFrozenCallStack işlevini sağlar, böylece başka kareler eklenemez.HasCallStack, withFrozenCallStack ile birlikte neden yığın çerçeveler ekliyor?

Basit senaryolarda, beklediğim gibi çalışır. Örneğin: Normalde foo çağırdığınızda

ghci> let foo :: HasCallStack => CallStack 
      foo = callStack 
ghci> foo 
[("foo",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci2", srcLocFile = "<interactive>", srcLocStartLine = 8, srcLocStartCol = 1, srcLocEndLine = 8, srcLocEndCol = 4})] 
ghci> withFrozenCallStack foo 
[] 

, bir yığın çerçevesi olsun ama withFrozenCallStack ile sarın zaman, yok. Mükemmel. örnek sadece biraz daha karmaşık hale Ancak, bu beklediğim gibi davrandığını durdurur: dolaylama bu basit katmanı ekleyerek

ghci> let foo :: CallStack 
      foo = bar 
      bar :: HasCallStack => CallStack 
      bar = callStack 
ghci> foo 
[("bar",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci9", srcLocFile = "<interactive>", srcLocStartLine = 24, srcLocStartCol = 11, srcLocEndLine = 24, srcLocEndCol = 14})] 
ghci> withFrozenCallStack foo 
[("bar",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci9", srcLocFile = "<interactive>", srcLocStartLine = 24, srcLocStartCol = 11, srcLocEndLine = 24, srcLocEndCol = 14})] 

, yığın çerçevesi hala eklenmiş olur, withFrozenCallStack uygulamama rağmen. Niye ya?

Kavramsal olarak, HasCallStack benim anlayış mevcut çağrı yığını pushCallStack örtülü bir kullanım gibi olduğunu ve pushCallStack donmuş bir çağrı yığını üzerinde hiçbir etkisi yoktur. O zaman neden withFrozenCallStack yukarıdaki yığın çerçevesinin çağrı yığına eklenmesini engellemiyor?

cevap

2

Kodunuzda foo, CallStack türünde statik bir değerdir. 'un'un HasCallStack kısıtlamasına sahip olmadığını unutmayın.

foo numaralı telefonu nasıl ve nerede kullandığınız önemli değildir, her zaman bu CallStack numaralı telefonu kullanır. foo'un kendisi bar kullanılarak tanımlanmıştır, HasCallStack makinelerini kullanır - sadece foo = [("bar",… tanımlayabilirsiniz.

HasCallStack => ekini, foo'nun imza türüne eklemeye çalışın. Şimdi beklediğiniz gibi davranıyor mu?

+0

Ahh, elbette, bu mantıklı. Haskell'deki örtük parametreler hakkındaki sezgilerim açıkça en iyisi değil, çünkü bu sadece 'HasCallStack' değil, örtük bir parametreye uygulanacaktır. Neyse, teşekkürler. –

+0

Neredeyse, ama pek de değil. Normal bir örtük parametresiyle, kısıtlamayı kullanmayı bıraktığınız yerde açıkça bağlı değilse bir hata alırsınız. Ancak 'HasCallStack' ile derleyici bunu algılar ve ilk çağrı yığınını büyülü olarak bağlar. –

+0

Aha, evet, bu mantıklı - yine haklısın. :) HasCallStack'in büyülü doğası kesinlikle biraz kafa karıştırıcı. Hâlâ HasCallStack'ın kısıtlamalarının nasıl sonuçlandığını incelediğimi tamamen anladığımı sanmıyorum, ama neyse ki bu benim için çok fazla sorun değil gibi görünüyor haha. –