将 where 子句带入 GHCi 调试器的范围

Bringing where clause into scope in GHCi debugger

今天早些时候,我试图调试以下 solve 函数的一个版本,但它给我带来了问题:

newtype Audience = Audience { byShyness :: [Int] }

solve :: Audience -> Int
solve (Audience originalCounts) = numFriendsAdded
  where numFriendsAdded = length $ filter id friendAdded
        friendAdded     = zipWith3 (\i c t -> i >= c + t) [0..] originalCounts alreadyStanding
        alreadyStanding = scanl (+) 0 modifiedCounts
        modifiedCounts  = zipWith (\a c -> if a then 1 else c) friendAdded originalCounts

在 GHCi (7.8.2) 中,我尝试按名称打破 solve,然后按 line/column,但它似乎没有带来 [=14= 中绑定的名称] 子句进入范围:

λ :b solve 
Breakpoint 0 activated at StandingOvation.hs:(20,1)-(24,89)
λ :main StandingOvation.example-input 
Case #1: Stopped at StandingOvation.hs:(20,1)-(24,89)
_result :: Int = _
λ numFriendsAdded
<interactive>:5:1: Not in scope: ‘numFriendsAdded’
λ :delete 0
λ :b 20 35
Breakpoint 1 activated at StandingOvation.hs:20:35-49
λ :main StandingOvation.example-input 
Case #1: Stopped at StandingOvation.hs:20:35-49
_result :: Int = _
numFriendsAdded :: Int = _
λ numFriendsAdded                                                                                                     
0
λ friendAdded
<interactive>:10:1: Not in scope: ‘friendAdded’

显然,就 Haskell 而言,它们在相互作用域内,但我需要做什么才能在调试时使它们可见?

不幸的是,GHCi 调试器不会在断点处使范围内的所有内容都可用。引用 from the user manual(7.8.2 和 7.10.1(最新)中的文本相同):

GHCi has provided bindings for the free variables[6] of the expression on which the breakpoint was placed (a, left, right), and additionally a binding for the result of the expression (_result). [...]

和脚注:

[6] We originally provided bindings for all variables in scope, rather than just the free variables of the expression, but found that this affected performance considerably, hence the current restriction to just the free variables.

本质上,只有在 GHCi 当前停止的表达式中直接提及局部变量,您才能看到它们。这让我想到了一个解决方法,虽然很傻但确实有效。将函数主线替换为:

solve (Audience originalCounts) =
    (friendAdded,alreadyStanding,modifiedCounts) `seq` numFriendsAdded

现在您感兴趣的所有变量都已在表达式中提及,因此您可以停下来查看它们。