[GHC] #11156: Type-changing record update catch-all in sum type doesn't typecheck

GHC ghc-devs at haskell.org
Wed Dec 2 21:04:28 UTC 2015


#11156: Type-changing record update catch-all in sum type doesn't typecheck
-------------------------------------+-------------------------------------
           Reporter:  afarmer        |             Owner:
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  7.10.2
  (Type checker)                     |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  GHC rejects
  Unknown/Multiple                   |  valid program
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Apologies for the confusing title/summary, but that is about as succinct
 as I could be.

 Rather than try to describe this in english, here is the smallest example
 I could repro with.

 I want to write this:

 {{{
 import Data.Char

 data R a
   = Foo { x :: a, y :: a }
   | Bar { x :: a }
   | Baz { x :: a }

 ordify :: R Char -> R Int
 ordify r@(Foo {}) = r { x = ord (x r), y = ord (y r) }
 ordify r          = r { x = ord (x r) }
 }}}

 But that fails to typecheck:

 {{{
 $ ghci Test.hs
 GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
 [1 of 1] Compiling Main             ( Test.hs, interpreted )

 Test.hs:10:21:
     Couldn't match type ‘Char’ with ‘Int’
     Expected type: R Int
       Actual type: R Char
     In the expression: r
     In the expression: r {x = ord (x r)}
 Failed, modules loaded: none.
 }}}

 Instead, I have to resort to enumerating all the remaining constructors:

 {{{
 import Data.Char

 data R a
   = Foo { x :: a, y :: a }
   | Bar { x :: a }
   | Baz { x :: a }

 ordify :: R Char -> R Int
 ordify r@(Foo {}) = r { x = ord (x r), y = ord (y r) }
 ordify (Bar x) = Bar (ord x)
 ordify (Baz x) = Baz (ord x)
 }}}

 The sum type has the property that every constructor has the field x, and
 some constructors have fields which are also parameterized over x's type
 'a'. I would expect my first example, with the catch-all record-update to
 typecheck, but it doesn't. I suspect GHC thinks the catch-all case of
 ordify might be passed a Foo constructor, in which case the record update
 would be ill-typed, even though that is impossible due to the first case
 matching Foo explicitly.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11156>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list