#4220: EmptyDataDecls + DeriveFunctor == Panic!
---------------------------------+------------------------------------------
    Reporter:  conal             |        Owner:  simonpj           
        Type:  bug               |       Status:  new               
    Priority:  normal            |    Milestone:  6.14.1            
   Component:  Compiler          |      Version:  6.12.3            
    Keywords:                    |     Testcase:                    
   Blockedby:                    |   Difficulty:                    
          Os:  Unknown/Multiple  |     Blocking:                    
Architecture:  Unknown/Multiple  |      Failure:  Compile-time crash
---------------------------------+------------------------------------------
Changes (by JulesBean):

 * cc: ju...@… (added)


Comment:

 For `Foldable` it suffices to define `foldMap` :

 {{{
 foldMap :: Monoid m => (a -> m) -> t a -> m
 }}}

 If you "don't have" anything of type `a` either because it's an
 EmptyDataDecl or because it's a constructor which doesn't mention the type
 variable, then the only possible result is `mempty`.

 {{{
 foldMap _ _ = mempty
 }}}

 That suffices to define an instance, but for efficiency(?) you could add
 the other methods directly.

 {{{
 fold :: Monoid m => t m -> m
 fold _ = mempty

 foldMap :: Monoid m => (a -> m) -> t a -> m
 foldMap _ _ = mempty

 foldr :: (a -> b -> b) -> b -> t a -> b
 foldr _ start _ = start

 foldl :: (a -> b -> a) -> a -> t b -> a
 foldl _ start _ = start

 foldr1 :: (a -> a -> a) -> t a -> a
 foldr1 _ _ = error "Foldable.foldr1"

 foldl1 :: (a -> a -> a) -> t a -> a
 foldl1 _ _ = error "Foldable.foldl1"
 }}}

 For `Traversable` it suffices to define `traverse`:

 {{{
 traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
 }}}

 Similar reasoning - if you don't have any `a` then you can't apply the
 function given, and there can be no applicative effects to consider
 because no value `f b` can be constructed. So, rather like in the functor
 case, you do a constructor by constructor conversion, wrapped in `pure`
 for no effects.

 {{{
 traverse _ (T2 a) = pure (T2 a) -- n.b. these two (T2 a) expressions are
 at a different type
 }}}

 By the same process as for Functor you might choose to go for the under-
 the-hood more efficient `pure . unsafeCoerce#`, or alternatively you can
 "delegate" the efficiency hack to the Functor instance and use `pure .
 fmap undefined`.

 Does that all sound reasonable?

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4220#comment:7>
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

Reply via email to