Debugging Haskell code

I'm still playing round with my random dieroll generation program. In doing so, I just hit a segmentation fault (I didn't think Haskell could *cause* a segfault!) I'm sure it's my code - I got this to compile by fiddling with types until the errors (which I didn't understand) went away. Certainly not the right way to code, I know, but never mind. The problem is that I have *no idea* how to begin debugging this. In C, Python, or any other imperative language, I'd put traces in, etc. But in Haskell, I don't even know where to start. I attach the code below. While help in the form of pointers to what I did wrong would of course be appreciated, what I'm really looking for is a pointer on how I'd find out for myself. (Hey! I just read the bit in the ghc manual which says if I am not using foreign or unsafe functions, a crash is a compiler bug. Did I find a compiler bug?) My code is below. All I did is ghc --make hist_3d6.hs, then run hist_3d6.exe. This is ghc 6.10.4 on Windows Vista Home 32-bit. Thanks for any help, Paul. import System.Random.Mersenne import qualified Data.Map as Map import Data.Map (Map) import Data.List takes :: Int -> [a] -> [[a]] takes n [] = [] takes n xs = take n xs : takes n (drop n xs) sums :: Num a => Int -> [a] -> [a] sums n xs = map sum (takes n xs) simulate :: Int -> IO [Double] simulate count = do gen <- newMTGen Nothing dice <- (randoms gen :: IO [Double]) return (take count dice) histogram :: Ord a => [a] -> [(a,Int)] histogram = Map.assocs . foldl' f Map.empty where f m k = Map.insertWith' (+) k 1 m simulation = do lst <- simulate 100000 return lst --return (histogram lst) main = do s <- simulation putStrLn (show s)

2009/9/27 Paul Moore
I'm still playing round with my random dieroll generation program. In doing so, I just hit a segmentation fault (I didn't think Haskell could *cause* a segfault!) I'm sure it's my code - I got this to compile by fiddling with types until the errors (which I didn't understand) went away. Certainly not the right way to code, I know, but never mind.
The problem is that I have *no idea* how to begin debugging this. In C, Python, or any other imperative language, I'd put traces in, etc. But in Haskell, I don't even know where to start.
I attach the code below. While help in the form of pointers to what I did wrong would of course be appreciated, what I'm really looking for is a pointer on how I'd find out for myself. (Hey! I just read the bit in the ghc manual which says if I am not using foreign or unsafe functions, a crash is a compiler bug. Did I find a compiler bug?)
My code is below. All I did is ghc --make hist_3d6.hs, then run hist_3d6.exe. This is ghc 6.10.4 on Windows Vista Home 32-bit.
Thanks for any help, Paul.
import System.Random.Mersenne import qualified Data.Map as Map import Data.Map (Map) import Data.List
takes :: Int -> [a] -> [[a]] takes n [] = [] takes n xs = take n xs : takes n (drop n xs)
sums :: Num a => Int -> [a] -> [a] sums n xs = map sum (takes n xs)
simulate :: Int -> IO [Double] simulate count = do gen <- newMTGen Nothing dice <- (randoms gen :: IO [Double]) return (take count dice)
histogram :: Ord a => [a] -> [(a,Int)] histogram = Map.assocs . foldl' f Map.empty where f m k = Map.insertWith' (+) k 1 m
simulation = do lst <- simulate 100000 return lst --return (histogram lst)
main = do s <- simulation putStrLn (show s) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
mersenne-random uses the FFI, so it's probably that. I just ran your code with mersenne-random-1.0 and didn't get a segfault. What version are you using?

2009/9/27 andy morris: > mersenne-random uses the FFI, so it's probably that. I just ran your > code with mersenne-random-1.0 and didn't get a segfault. What version > are you using? Not entirely sure, I just did a cabal install a short while back. >cabal list mersenne Warning: The package list for 'hackage.haskell.org' is 19 days old. Run 'cabal update' to get the latest list of available packages. * mersenne-random Synopsis: Generate high quality pseudorandom numbers using a SIMD Fast Mersenne Twister Latest version available: 1.0 Latest version installed: [ Not installed ] Homepage: http://code.haskell.org/~dons/code/mersenne-random License: BSD3 * mersenne-random-pure64 Synopsis: Generate high quality pseudorandom numbers purely using a Mersenne Twister Latest version available: 0.2.0.2 Latest version installed: [ Not installed ] Homepage: http://code.haskell.org/~dons/code/mersenne-random-pure64/ License: BSD3 That's odd, it seems to be saying it's not installed at all! Hmm, no - I did a cabal install --user (because Vista doesn't let me do site-wide installs), looks like cabal list doesn't pick up user installs. Hmm, cabal install mersenne-random --user didn't do anything, but cabal install mersenne-random --user --reinstall did reinstall it, and now it seems to work. Odd. Thanks for the help - presumably the lesson for me is that a crash implies that unless I am using FFI or unsafe functions, I should look to any libraries I use. It begs the question of how I'd prove that was the problem if there hadn't been an updated version of the library - I guess I'd use the standard random module & see if that worked. Paul.

On Sun, Sep 27, 2009 at 9:17 PM, Paul Moore
That's odd, it seems to be saying it's not installed at all! Hmm, no - I did a cabal install --user (because Vista doesn't let me do site-wide installs), looks like cabal list doesn't pick up user installs.
Hmm, cabal install mersenne-random --user didn't do anything, but cabal install mersenne-random --user --reinstall did reinstall it, and now it seems to work.
To find out what GHC picks up automatically: $ ghc-pkg list /home/dougal/lib/ghc-6.10.3/./package.conf: Cabal-1.6.0.3, HUnit-1.2.0.3, QuickCheck-1.2.0.0, array-0.2.0.0, base-3.0.3.1, base-4.1.0.0, bytestring-0.9.1.4, containers-0.2.0.1, directory-1.0.0.3, (dph-base-0.3), (dph-par-0.3), (dph-prim-interface-0.3), (dph-prim-par-0.3), (dph-prim-seq-0.3), (dph-seq-0.3), extensible-exceptions-0.1.1.0, filepath-1.1.0.2, (ghc-6.10.3), ghc-prim-0.1.0.0, haddock-2.4.2, haskell-src-1.0.1.3, haskell98-1.0.1.0, hpc-0.5.0.3, html-1.0.1.2, integer-0.1.0.1, mtl-1.1.0.2, network-2.2.1, old-locale-1.0.0.1, old-time-1.0.0.2, packedstring-0.1.0.1, parallel-1.1.0.1, parsec-2.1.0.1, pretty-1.0.1.0, process-1.0.1.1, random-1.0.0.1, regex-base-0.72.0.2, regex-compat-0.71.0.1, regex-posix-0.72.0.3, rts-1.0, stm-2.1.1.2, syb-0.1.0.1, template-haskell-2.3.0.1, time-1.1.3, unix-2.3.2.0, xhtml-3000.2.0.1 /home/dougal/.ghc/i386-linux-6.10.3/package.conf: HTTP-4000.0.4, X11-1.4.5, X11-xft-0.3, benchpress-0.2.2.3, cairo-0.10.1, colour-2.3.0, cpphs-1.9, darcs-2.2.1, data-default-0.2, diagrams-0.2, gd-3000.4.0, gio-0.10.1, glib-0.10.1, gtk-0.10.1, hashed-storage-0.3.7, haskeline-0.6.1.6, haskell-src-exts-1.1.4, hscolour-1.15, mmap-0.4.1, soegtk-0.10.1, split-0.1.1, svgcairo-0.10.1, tagsoup-0.6, terminfo-0.2.2.1, terminfo-0.3.0.2, uniplate-1.2.0.3, utf8-string-0.3.4, xmonad-0.8.1, xmonad-contrib-0.8.1, zlib-0.5.0.0, zlib-0.5.2.0 You should get everything hanging about, installed system-wide or in your home directory. I assume this works much the same for Windows. D

Am Sonntag 27 September 2009 22:02:45 schrieb andy morris:
mersenne-random uses the FFI, so it's probably that. I just ran your code with mersenne-random-1.0 and didn't get a segfault.
Yup, works here, too. And everything but mersenne-random should be fool-proof.
What version are you using?

On Sun, Sep 27, 2009 at 3:50 PM, Paul Moore
The problem is that I have *no idea* how to begin debugging this.
I've had great success debugging a large program by loading the Main module into ghci after setting GHC extensions, changing the search path, and setting break on errors. If you then place calls to the error function at the right location, and trace the execution, you'll be able to get a stack trace of the context in which the error function was called. John

On 2009-09-28 22:53 -0400 (Mon), John D. Ramsdell wrote:
I've had great success debugging a large program by loading the Main module into ghci after setting GHC extensions, changing the search path, and setting break on errors. If you then place calls to the error function at the right location, and trace the execution, you'll be able to get a stack trace of the context in which the error function was called.
Yes, I often use the interpreter to poke at and play with my code.
Note that by using the -odir and so forth options, you can mix interpreted
and compiled code, so that you need interpret only the particular modules
you're trying to debug, and all the rest the application can run at full,
compiled speed.
cjs
--
Curt Sampson

On Sun, Sep 27, 2009 at 12:50 PM, Paul Moore
The problem is that I have *no idea* how to begin debugging this. In C, Python, or any other imperative language, I'd put traces in, etc. But in Haskell, I don't even know where to start.
One of the standard modules is Debug.Trace module, which does allow you to print information to the console. It just may come in an odd order and of course, it can change your program if you force evaluation. Under the covers it is really "unsafePerformIO $ putStrLn msg", i.e., it just prints to the console. I've found that forcing a flush on the output stream can be useful too, so I've defined my own trace before too. There is also the GHC debugger, which is best described in the user manual - read the section there to learn more. If you hadn't already received help on the list, either of these could be used to narrow down where the crash is occurring. Justin
participants (7)
-
andy morris
-
Curt Sampson
-
Daniel Fischer
-
Dougal Stanton
-
John D. Ramsdell
-
Justin Bailey
-
Paul Moore