<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Yeah, I changed my example file along the way. Originally I intended not to have the D there.<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 16, 2017, at 3:55 PM, David Feuer <<a href="mailto:david.feuer@gmail.com" class="">david.feuer@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="auto" class=""><div class="">fmap2 is not a legitimate implementation, and is only accepted without warning because of a type checker bug. C a is actually inhabited, by D undefined undefined. If you wrote data C a = D !Void !Void, that would be a different story, and would have no bottoms. fmap1 is legitimate, and completely equivalent, semantically, to the usual derived definition.</div><div dir="auto" class=""><div class="gmail_extra" dir="auto"><br class=""><div class="gmail_quote">On Jan 16, 2017 6:45 PM, "Eric Mertens" <<a href="mailto:emertens@gmail.com" class="">emertens@gmail.com</a>> wrote:<br type="attribution" class=""><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">It’s possible that empty case produces exactly the same eventual result. Simply looking at the core I was seeing a new bottom being potentially introduced.</div><div class=""><br class=""></div><div class="">Given:</div><div class=""><br class=""></div><div class="">data C a = D Void Void<br class=""><br class="">fmap1, fmap2 :: (a -> b) -> C a -> C b<br class="">fmap1 _ = coerce<br class="">fmap2 _ = \case {}</div><div class=""><br class=""></div><div class="">I get:</div><div class=""><br class=""></div><div class="">fmap4 = \ @ a_a2FE @ b_a2FF _ tpl_B2 -> tpl_B2<br class="">fmap1 = fmap4 `cast` ...<br class="">fmap5 = \ @ b_a2FX -> <wbr class="">patError "Demo.hs:12:11|case"#<br class="">fmap2 = \ @ a_a2FW @ b_a2FX _ _ -> fmap5<br class=""><br class=""></div><div class="">And with the goal being the avoidance of new bottoms, fmap1’s generated core looked nicer.</div><div class="elided-text"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 16, 2017, at 3:38 PM, David Feuer <<a href="mailto:david.feuer@gmail.com" target="_blank" class="">david.feuer@gmail.com</a>> wrote:</div><br class="m_6398335891544265430Apple-interchange-newline"><div class=""><div dir="auto" class="">Semantically, this is precisely equivalent to the empty case. Is there some reason to prefer it?</div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Jan 16, 2017 6:35 PM, "Eric Mertens" <<a href="mailto:emertens@gmail.com" target="_blank" class="">emertens@gmail.com</a>> wrote:<br type="attribution" class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">A possible derived fmap implementation for any empty data type could be `fmap _ = coerce`. This would ensure that any bottom was passed through. Of course this would run into problems with an explicit "type role" declaration on the empty data type.<div class=""><br class=""></div><div class="">-- </div><div class="">Eric</div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, Jan 16, 2017 at 1:08 PM Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com" target="_blank" class="">ryan.gl.scott@gmail.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">For reference, Data.Void.Void currently has no Enum or Bounded<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
instance. It does have an Ix instance [1]:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
instance Ix Void where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
range _ = []<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
index _ = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
inRange _ = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
rangeSize _ = 0<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
Ryan S.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
-----<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
[1] <a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Void.html#line-53" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">http://hackage.haskell.org/pac<wbr class="">kage/base-4.9.1.0/docs/src/Dat<wbr class="">a.Void.html#line-53</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
On Mon, Jan 16, 2017 at 4:03 PM, David Feuer <<a href="mailto:david.feuer@gmail.com" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">david.feuer@gmail.com</a>> wrote:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> I have no intuition about what Enum should do about void datatypes;<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> it's too broken. Bounded has one sensible default (minBound and<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> maxBound should produce an error message naming the type and explain<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> that it has no values). Ix gets pretty weird here. I would think<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> range = const []<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> index _ x = case x of<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> inRange _ _ = False OR inRange _ x = case x of {} (is it sensible<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> to ask if _|_ is in an empty range?)<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> rangeSize = const 0<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
> On Mon, Jan 16, 2017 at 3:37 PM, Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">ryan.gl.scott@gmail.com</a>> wrote:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> Thanks for the clarification. I definitely agree that the current<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> error-based behavior for classes where T occurs in a negative position<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> is suboptimal. If I understand your position correctly, then you<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> advocate determining what the derived code for methods in which T<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> occurs negatively on a case-by-case basis? How about I just list all<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> of the stock derivable classes, give example instances, and see if you<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> agree with them?<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> data Empty a deriving (Eq, Ord, Read, Show, Functor, Foldable,<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> Traversable, Lift, Generic, Data)<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> ===><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Eq (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> _ == _ = True<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Ord (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> compare _ _ = EQ<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Read (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> readPrec = parens pfail<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Show (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> showsPrec _ = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Functor Empty where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> fmap _ = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Foldable Empty where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> foldr _ z _ = z<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> foldMap _ _ = mempty<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Traversable Empty where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> traverse _ = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Lift (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> lift = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Generic (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> from = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> to = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> instance Data (Empty a) where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> gfoldl _ = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> gunfold _ _ c = constrIndex c of {}<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> toConstr = absurd<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> dataTypeOf = mkDataType "Empty" []<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> absurd :: Empty a -> b<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> absurd x = case x of {}<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> Note I didn't list Bounded, Enum, or Ix because GHC currently forbids<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> you from deriving instances of those for empty datatypes, even with<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> -XStandaloneDeriving on. Do you think we should revisit this?<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> Ryan S.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> On Mon, Jan 16, 2017 at 3:09 PM, Edward Kmett <<a href="mailto:ekmett@gmail.com" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">ekmett@gmail.com</a>> wrote:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>> By current behavior, I was referring to the behavior of Void, not deriving.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>> I think the current deriving behavior on this front is suboptimal by the<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>> reasoning given in my previous post.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>> -Edward<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>> On Mon, Jan 16, 2017 at 1:51 PM, Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">ryan.gl.scott@gmail.com</a>> wrote:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> I think I mostly agree with everything you've said, but I'm not sure I<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> understood all the details, so let me try to recap:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > In the case it doesn't occur at all or occurs only positively, er... we<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > don't care. We're not case analyzing it =)<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> Indeed there's only one stock class you can derive where the type<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> occurs only positively, and that's Read, which already has nice<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> behavior for empty datatypes:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> data Empty<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> deriving instance Read Empty<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ====><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> instance Read Empty where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> readPrec = parens pfail<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> So indeed, this an easy case.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > In the case of it occurring in both positive and negative position we<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > have the option to 'pass it through' to exchange the bottom. In the case of<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > changing the behavior of Functor and the like we're not actually changing<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > the definedness of the result, we're merely choosing between "equivalent"<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > bottoms. This is a rather exceptional case, but the ability to preserve<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > placed bottoms in a structure in case they have meaning to the user seems<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > quite valuable.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> To be clear, this corresponds to David's proposal to use -XEmptyCase,<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> right?<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > In the case of negative position only, the current behavior is more<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > defined than the stricter behavior Ryan proposes. I personally very much<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > favor keeping Eq, Ord, etc. as defined as possible for Void, V1 and the like<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > with the existing behavior. 'a' occurs in negative position only for these<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > cases.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> What do you mean by "the current behavior" here? For instance, if you had:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> data Empty<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> deriving instance Eq Empty<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> Are you defining "the current behavior" to mean this? That is, what<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> GHC currently spits out today:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> instance Eq Empty where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> (==) = error "Void =="<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> Or by "current behavior", do you mean the (manually written) instance<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> that Void has:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> instance Eq Void where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> _ == _ = True<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> These two instances are quite different, after all.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > Similarly the existing practice of not doing wasted work and producing<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > more defined results, also seems valuable. Aiming for "consistency" here<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > seems to be pursuing a goal that doesn't actually help anyone and just makes<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > stuff less defined.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> Fully agree.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> Ryan S.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> On Mon, Jan 16, 2017 at 12:55 PM, Edward Kmett <<a href="mailto:ekmett@gmail.com" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">ekmett@gmail.com</a>> wrote:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > There are really four cases to consider for deriving purposes.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > Some type T occurs positively, negative, not at all, or in both.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > * In the case it doesn't occur at all or occurs only positively, er...<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > we<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > don't care. We're not case analyzing it =)<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > * In the case of negative position only, the current behavior is more<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > defined than the stricter behavior Ryan proposes. I personally very much<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > favor keeping Eq, Ord, etc. as defined as possible for Void, V1 and the<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > like<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > with the existing behavior. 'a' occurs in negative position only for<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > these<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > cases.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > * In the case of it occurring in both positive and negative position we<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > have<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > the option to 'pass it through' to exchange the bottom. In the case of<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > changing the behavior of Functor and the like we're not actually<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > changing<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > the definedness of the result, we're merely choosing between<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > "equivalent"<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > bottoms. This is a rather exceptional case, but the ability to preserve<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > placed bottoms in a structure in case they have meaning to the user<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > seems<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > quite valuable.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > Similarly the existing practice of not doing wasted work and producing<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > more<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > defined results, also seems valuable. Aiming for "consistency" here<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > seems to<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > be pursuing a goal that doesn't actually help anyone and just makes<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > stuff<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > less defined.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > -Edward<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > On Mon, Jan 16, 2017 at 9:25 AM, Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">ryan.gl.scott@gmail.com</a>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> > wrote:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> To be clear, if you have:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> data V a deriving Functor<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> David is proposing in #13117 [1] that the derived instance use<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> -XEmptyCase instead of the current error-based implementation:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> instance Functor V where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> fmap _ x = case x of {}<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> This seems fine and well, but given that #13117 is basically a<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> continuation of another discussion in #7401 [2], I feel like if we're<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> going to tackle the issue of derived instances for empty data<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> declaration, we should solve it for all stock classes.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> In particular, there are two thorny issues to consider here. What if<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> we have this instead?<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> data V2 deriving Eq<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> What instance should this produce? Reid Barton proposed in #10577 [3]<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> that it should be:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> instance Eq V2 where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> a == _ = case a of {}<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> But we have a choice here, since (==) has multiple arguments! The<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> definition could also conceivably be:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> instance Eq V2 where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> _ == b = case b of {}<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> Is there a uniform policy we can decide for functions with multiple<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> arguments like this? In fmap, it's unambiguous since there's only one<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> argument of type f a.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> Another issue to consider is that if we adopted this convention for<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> derived Eq instances for empty datatypes, we'd actually be going<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> against the convention set for Data.Void. As noted in [4], this is the<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> current Eq instance for Void:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> instance Eq Void where<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> _ == _ = True<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> I'm not proposing that we change this definition, since there are many<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> good reasons to have it this way (see the thread in [5] for Edward<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> Kmett's convincing argument in favor of the current Eq Void instance).<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> Rather, I'm asking if we would be OK with having this<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> discrepancy--that is, deriving Eq for your own Void2 type would<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> produce a different instance. Personally, I'd be fine with it, but I<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> think we should ask for the community's input as well.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> So sorry to hijack this thread, David, but we really should answer<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> these two questions as well:<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> 1. What do we do in ambiguous cases like derived (==) implementations<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> for empty datatypes?<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> 2. Are we fine with derived instances for empty datatypes sometimes<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> being different than the corresponding instances for Data.Void?<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> Ryan S.<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> -----<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> [1] <a href="https://ghc.haskell.org/trac/ghc/ticket/13117" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">https://ghc.haskell.org/trac/g<wbr class="">hc/ticket/13117</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> [2] <a href="https://ghc.haskell.org/trac/ghc/ticket/7401#comment:46" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">https://ghc.haskell.org/trac/g<wbr class="">hc/ticket/7401#comment:46</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> [3] <a href="https://ghc.haskell.org/trac/ghc/ticket/10577" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">https://ghc.haskell.org/trac/g<wbr class="">hc/ticket/10577</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> [4] <a href="https://mail.haskell.org/pipermail/libraries/2015-July/025959.html" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">https://mail.haskell.org/piper<wbr class="">mail/libraries/2015-July/02595<wbr class="">9.html</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> [5] <a href="https://mail.haskell.org/pipermail/libraries/2015-July/025965.html" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">https://mail.haskell.org/piper<wbr class="">mail/libraries/2015-July/02596<wbr class="">5.html</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> ______________________________<wbr class="">_________________<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> Libraries mailing list<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> <a href="mailto:Libraries@haskell.org" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">Libraries@haskell.org</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> >> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">http://mail.haskell.org/cgi-bi<wbr class="">n/mailman/listinfo/libraries</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>>> ><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>>><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> ______________________________<wbr class="">_________________<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> Libraries mailing list<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> <a href="mailto:Libraries@haskell.org" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">Libraries@haskell.org</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
>> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">http://mail.haskell.org/cgi-bi<wbr class="">n/mailman/listinfo/libraries</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
______________________________<wbr class="">_________________<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
Libraries mailing list<br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
<a href="mailto:Libraries@haskell.org" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">Libraries@haskell.org</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" class="m_6398335891544265430m_-8279648192330241193gmail_msg" target="_blank">http://mail.haskell.org/cgi-bi<wbr class="">n/mailman/listinfo/libraries</a><br class="m_6398335891544265430m_-8279648192330241193gmail_msg">
</blockquote></div>
</blockquote></div></div>
</div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></div>
</div></blockquote></div><br class=""></div></body></html>