Why no Fractional instance for Sum
Asked Answered
N

1

6

In ghci:

Data.Semigroup> 0.1 :: Sum Double
<interactive>:2:1: error: [GHC-39999]
    • No instance for ‘Fractional (Sum Double)’
        arising from the literal ‘0.1’
    • In the expression: 0.1 :: Sum Double
      In an equation for ‘it’: it = 0.1 :: Sum Double

Is this an oversight, or is there a principled reason not to make this instance? (I know that addition is not associative for Double -- but instance Monoid (Sum Double), the actually problematic instance for that objection, already exists anyway!)

Niigata answered 7/9 at 17:45 Comment(3)
Relevant GHC issue: gitlab.haskell.org/ghc/ghc/-/issues/18161Killam
@NaïmFavier Great find, thank you! If you turn that into an answer, I'll accept it.Niigata
This is imho the downside of such "marker interfaces" like Sum: you essentially have to implement all the instances for instance C a => C (Sum a) for all classes, except the ones you override. Especially if C is from another package, that is thus complicated, and often makes Sum less powerful.Kevel
K
4

@NaïmFavier answered this in their comment with a reference to ticket #18161, as Emily Pillmore said:

It'd be confusing for me to divide two Sum values. I think I'm leaning harder in the "no" direction because intent matters.

It thus to some extent depends on whether you see Sum as a construct that holds values, and then is only used to fold these, and then retrieve the value the result holds, or as not much more as a "marker interface[wiki] and thus that Sum a is noth much more than an a that is marked as a sum, and where typeclasses a is a member of, also imply that Sum a should be a member of.

For the last one, that thus should mean that one essentially tries to implement it as:

instance C a => C (Sum a) where
    -- …

for as much Cs as possible, except the ones for which the "marker" is used (in this case thus Monoid and Semigroup).

Kevel answered 7/9 at 17:45 Comment(1)
Very interesting ! Now that you put it like this, it'd definitely lovely to have these "marker interfaces" everywhere in the Base library (in particular the Identity functor). It looks fairly easy to implement using overlapping instances and it makes a lot of sense, to me at least. But of course such a change would have huge implications ... but it would have been nice :-)Ewold

© 2022 - 2024 — McMap. All rights reserved.