How does one debug infinite recursion in Haskell?

483 views Asked by At

How would one debug this (obviously) flawed program using GHC's profiling tools? The program enters an infinite recursion within the second clause of frobnicate.

-- Foo.hs
frobnicate :: Show a => Maybe a -> String
frobnicate Nothing = ""
frobnicate x       = case frobnicate x of
  "" -> "X"
  _  -> show x

main :: IO ()
main = print (frobnicate (Just "" :: Maybe String))

The example might look contrived, but it's actually stripped down version of a real bug I encountered today.

In an imperative language one the mistake would be obvious as the stack trace would say something like frobnicate -> frobnicate -> frobnicate -> .... But how would one discover this in Haskell? How would one narrow down the blame to this one particular function?

I tried something akin to the following:

ghc -fforce-recomp -rtsopts -prof -fprof-auto Foo.hs
./Foo +RTS -M250M -i0.001 -h
hp2ps -c Foo.hp

where the -M250M flag is added to ensure it doesn't kill the machine, -i0.001 increases the profiling frequency in an attempt to catch the overflow in action (which happens very fast).

This produces this rather unhelpful plot:

enter image description here

There is no obvious overflow in this plot. The y-axis doesn't go past even a single megabyte! What am I doing wrong here?

0

There are 0 answers