
#10447: DeriveFoldable rejects instances with constraints in last argument of data type -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: #8678 | Differential Revisions: -------------------------------------+------------------------------------- Comment (by ekmett): Simon's examples definitely give me pause. So putting aside type equality constraints for a moment, the other cases seem unambiguous. This would allow things like {{{ data Set a where Empty :: Set a NonEmpty :: Ord a => Tree a }}} but wouldn't get us {{{ data Val a where Int :: Int -> Val Int Char :: Char -> Val Char }}} To get there, it seems to me that `shachaf`'s `E` example seems a step too far. Given {{{ data Bar a = Bar a data Foo a = Foo (Bar a b) }}} We don't attempt to walk into `Bar` and recursing into something that isn't the last argument or relying on expansion seems "deeply magic", and ill specified -- where does the recursion stop? On the other hand, if we take Simon's examples, and say it'd be nice to generate the same code for semantically equal data declarations, and to allow whatever constraints we want, then using the type equality constraint (a ~ X) as part of the check for naked `a`s and accepting a naked `X` as an `a` seems very coherent. Then in the presence of `(a ~ X)`, folding over all `X`'s immediately inside the structure we're in and delegating all `(f X)`'s to the `Foldable` for `f` would be consistent with the existing behavior. If you wanted something more exotic where you skipped over some of them, you'd have to write a hand-rolled instance. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10447#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler