Earlier today, I was trying to debug a version of the below solve
function that was giving me problems:
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
In GHCi (7.8.2) I tried to break on solve
by name, then by line/column, but it didn't seem to bring the names bound in the where
clause into scope:
λ :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’
Obviously, they're in mutual scope as far as Haskell is concerned, but what do I need to do to make them visible when debugging?
Unfortunately, the GHCi debugger does not make everything in scope available at a breakpoint. To quote from the user manual (text identical in 7.8.2 and 7.10.1 (latest)):
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
). [...]
and the footnote:
[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.
Essentially, you can only see local variables if they are mentioned directly in the expression GHCi is currently stopped at. Which makes me think of a workaround, which although pretty silly does work. Replace the main line of the function by:
solve (Audience originalCounts) =
(friendAdded,alreadyStanding,modifiedCounts) `seq` numFriendsAdded
Now all the variables you're interested in are mentioned in the expression, so you can stop at it to see them all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With