#1584: problem presenting with explicit pattern matching
-----------------------+----------------------------------------------------
Reporter: guest | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 6.6.1
Severity: normal | Keywords:
Difficulty: Unknown | Os: Linux
Testcase: | Architecture: x86
-----------------------+----------------------------------------------------
Hi all,
I believe I've found a bug in ghc 6.6.1.
From Chapter 9. What to do when something goes wrong
“I think GHC is producing incorrect code”:
Unlikely :-)
And yet I'm out of ideas on why my code is acting the way it
does. I've got a tiny program for the towers of hanoi. In
my step function moving one disk to the next peg I seem to
be hitting a bug for explicit pattern matching. I have a
small example file (included below) to detail the issue.
1. What kind of machine am I running on?
{{{
$ uname -a
Linux lanny-lnx 2.4.21-32.0.1.EL #1 Tue May 17 18:01:37 EDT 2005 i686 i686
i386 GNU/Linux
}}}
I have also reproduced the bug (using ghc 6.6.1) on a Mac OS
X system. My linux box uses the rpm install from haskell.org/ghc
but on the mac I built ghc from the ground up (via
http://darwinports.com).
2. What version of gcc am I using?
{{{
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-52)
}}}
The mac is using the latest Xcode so it's got gcc 4.0.x
3. Complete ghci -v run showing problem.
{{{
$ ghci -v hanoi_bug.hs
___ ___ _
/ _ \ /\ /\/ __(_)
/ /_\// /_/ / / | | GHC Interactive, version 6.6.1, for Haskell 98.
/ /_\\/ __ / /___| | http://www.haskell.org/ghc/
\____/\/ /_/\____/|_| Type :? for help.
Using package config file: /opt/ghc-6.6.1/lib/i386-unknown-
linux/package.conf
wired-in package base mapped to base-2.1.1
wired-in package rts mapped to rts-1.0
wired-in package haskell98 mapped to haskell98-1.0
wired-in package template-haskell mapped to template-haskell-2.1
Hsc static flags: -static
Loading package base ... linking ... done.
wired-in package base mapped to base-2.1.1
wired-in package rts mapped to rts-1.0
wired-in package haskell98 mapped to haskell98-1.0
wired-in package template-haskell mapped to template-haskell-2.1
*** Parser:
*** Desugar:
*** Simplify:
*** CorePrep:
*** ByteCodeGen:
*** Parser:
*** Desugar:
*** Simplify:
*** CorePrep:
*** ByteCodeGen:
wired-in package base mapped to base-2.1.1
wired-in package rts mapped to rts-1.0
wired-in package haskell98 mapped to haskell98-1.0
wired-in package template-haskell mapped to template-haskell-2.1
*** Chasing dependencies:
Stable obj: []
Stable BCO: []
unload: retaining objs []
unload: retaining bcos []
Upsweep completely successful.
*** Deleting temp files:
Deleting:
*** Chasing dependencies:
Stable obj: []
Stable BCO: []
unload: retaining objs []
unload: retaining bcos []
compile: input file hanoi_bug.hs
*** Checking old interface for main:Main:
[1 of 1] Compiling Main ( hanoi_bug.hs, interpreted )
*** Parser:
*** Renamer/typechecker:
*** Desugar:
Result size = 1076
*** Simplify:
Result size = 1523
Result size = 1323
Result size = 1323
*** Tidy Core:
Result size = 1323
*** CorePrep:
Result size = 1641
*** ByteCodeGen:
*** Deleting temp files:
Deleting:
Upsweep completely successful.
*** Deleting temp files:
Deleting:
Ok, modules loaded: Main.
*Main> main
*** Parser:
*** Desugar:
*** Simplify:
*** CorePrep:
*** ByteCodeGen:
[True,True,True,False,False,True]
*Main> :q
Leaving GHCi.
*** Deleting temp files:
Deleting:
*** Deleting temp dirs:
Deleting:
}}}
5. What program behavior is wrong?
main is recording a list of properties which should all return True.
The behavior is the same for compiled rather than interpreted code
on both the linux and mac systems.
6. Source code demonstrating the problem.
{{{
$ cat hanoi_bug.hs
-- A Task is a tuple of
-- n :: The number of disks to move
-- i :: The initial peg
-- a :: The auxillary peg
-- f :: The final peg
type Task = (Int, Int, Int, Int)
data Tower a = Tower a a a
deriving (Eq, Show)
peg :: Int -> Tower [a] -> [a]
peg 1 (Tower a b c) = a
peg 2 (Tower a b c) = b
peg 3 (Tower a b c) = c
mkTower :: Task -> [a] -> [a] -> [a] -> Tower [a]
mkTower (_,1,2,3) a b c = Tower a b c
mkTower (_,1,3,2) a b c = Tower a c b
mkTower (_,2,1,3) a b c = Tower b a c
mkTower (_,2,3,1) a b c = Tower b c a -- BUG! returns (Tower c a b)
mkTower (_,3,1,2) a b c = Tower c a b -- BUG! returns (Tower b c a)
mkTower (_,3,2,1) a b c = Tower c b a
step :: Task -> Tower [a] -> Tower [a]
step task@(_,i,a,f) tower =
let pi = peg i tower
pa = peg a tower
pf = peg f tower
in
mkTower task (tail pi) pa (head pi : pf)
prop_test123 = step (1,1,2,3) (Tower [1] [3] [2]) == Tower [] [3]
[1,2]
prop_test132 = step (1,1,3,2) (Tower [1] [2] [3]) == Tower [] [1,2] [3]
prop_test213 = step (1,2,1,3) (Tower [3] [1] [2]) == Tower [3] []
[1,2]
prop_test231 = step (1,2,3,1) (Tower [2] [1] [3]) == Tower [1,2] [] [3]
prop_test312 = step (1,3,1,2) (Tower [3] [2] [1]) == Tower [3] [1,2] []
prop_test321 = step (1,3,2,1) (Tower [2] [3] [1]) == Tower [1,2] [3] []
checkProps = [ prop_test123
, prop_test132
, prop_test213
, prop_test231
, prop_test312
, prop_test321
]
main :: IO ()
main = print checkProps
}}}
7. If you are a hero...
Sorry. Not yet. At a guess the book-keeping for explicit pattern
matches is getting mixed up. Note that mkTower does provide the
correct permutations, it's just that two of them are mixed up.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/1584>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs