rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Enable InstanceSig by default

Open nomeata opened this issue 8 years ago • 15 comments

Rendered version: https://github.com/nomeata/rfcs/blob/instancesigs/0000-instancesigs.rst

nomeata avatar Nov 01 '16 19:11 nomeata

I'm strongly in favour of this proposal. From a teaching perspective, it's annoying to not be able to write the signatures of instances.

My only niggle is the inconsistent naming of the language extension itself: we have KindSignatures and PatternSignatures, so I think these ought to be called InstanceSignatures.

zenzike avatar Nov 02 '16 11:11 zenzike

Strongly in favor of this proposal as well, but can we change it to InstanceSignatures, please, echoing @zenzike ? Although it would be on by default, and so the only users who type the name would be saying -XNoInstanceSignatures..... and there seems to be absolutely no downsides to enabling this by default (other than lack of Haskell98/2010 conformity). So perhaps it's not worth the bother if the whole thing is going to be deprecated anyway.

goldfirere avatar Nov 02 '16 12:11 goldfirere

So perhaps it's not worth the bother if the whole thing is going to be deprecated anyway.

We still need a proposal to allow this in the new report, even if it is not a language extension, right?

nomeata avatar Nov 02 '16 13:11 nomeata

Yes. The "not worth the bother" part was about renaming InstanceSigs to InstanceSignatures.

goldfirere avatar Nov 02 '16 13:11 goldfirere

I'm +1 on this extension, because I also think it's an oddly strange restriction, when we can give signatures in so many other scopes. But I am going to highlight this bit for a moment:

If people really feel the need to that there needs to be something to be discussed for the sake of having an discussion, one might discuss the choice of GHC to allow more general types that required by the instance.

This seems to be just fine to me, if I'm understanding you correctly. After all, you can give a more general type than "required" to lot of different functions, so this seems consistent!

Assuming the rest of us agree, then, it'd be best to just move this sentence out of "Unresolved questions" bracket. And also-- it's worded a little oddly since it directly references the proposal process itself; it's sort of "breaking the fourth wall" which makes the "flow" of reading break a bit.

But also... please! Provide a code example, especially if this will be the case. Yes, this extension is trivial from our POV, but anyone who comes and reads it needs to be able to clearly, unambiguously understand it. It's easiest to do this with a small piece of code (and, you can also take the opportunity to demo more general instance signatures, as mentioned).

thoughtpolice avatar Nov 03 '16 18:11 thoughtpolice

I did now include the GHC doc as the detailed description.

nomeata avatar Nov 03 '16 19:11 nomeata

Note that InstanceSigs + ScopedTypeVariables is a bit unintuitive, because the type variables in the class are already scoped over the entire definition. For example,

class Foo a where
  bar :: Ord b => b -> a

instance What a => Foo a where
  bar :: forall b. Ord b => b -> a -- not "forall a b."
  bar = ...
    where 
      helper1 :: b -- needs ScopedTypeVariables
      helper1 = ...

      helper2 :: a -- doesn't need ScopedTypeVariables
      helper2 = ...

Just a point I thought I'd mention here.

mitchellwrosen avatar Dec 14 '16 02:12 mitchellwrosen

Good point. I hope that ScopedTypeVariables will also be a default in a future standard :-)

Is there anything reasonable we can do to improve this corner case?

nomeata avatar Dec 14 '16 02:12 nomeata

This all seems hunky-dory to me. The instance declaration brings a into scope, and so I shouldn't expect to bring it into scope again in the instance sig.

However, I'm not sure I agree with your "doesn't need ScopedTypeVariables" comment, as I thought type variables in instance heads were brought into scope only with that extension. (This is in contrast to type variables in class heads, which are always brought into scope.)

goldfirere avatar Dec 14 '16 03:12 goldfirere

@goldfirere I guess I meant it's a little bit inconsistent, as in, one might expect they'd have to write

instance forall a. What a => Foo a where

to get a to scope over the body and any locally defined helper functions, a la scoped type variables.

mitchellwrosen avatar Dec 14 '16 03:12 mitchellwrosen

@goldfirere Regarding your second point about not needing ScopedTypeVariables, it's true! (Unless I'm missing something).

This compiles fine:

class What a where
  what :: a

instance What (Maybe a) where
  what = x
    where
      x :: Maybe a
      x = Nothing

I think if this were true,

type variables in instance heads were brought into scope only with that extension

you'd get a "couldn't match type a with a1" error.

mitchellwrosen avatar Dec 14 '16 04:12 mitchellwrosen

Err, except that by my logic, this should be a type error, but it isn't:

class What a where
  what :: a

instance What (Maybe a) where
  what :: Maybe a
  what = undefined :: b

mitchellwrosen avatar Dec 14 '16 04:12 mitchellwrosen

Ok, @goldfirere is correct that you need ScopedTypeVariables if you want to refer to type variables in the instance head or in polymorphic typeclass functions, so there's actually no strange interaction with InstanceSigs at all!

mitchellwrosen avatar Dec 14 '16 04:12 mitchellwrosen

I agree with @mitchellwrosen that it is odd that instance Foo a where ... brings a into scope without an explicit forall. But that's orthogonal to this proposal. Thanks, @mitchellwrosen , for working all that out!

goldfirere avatar Dec 14 '16 13:12 goldfirere

I fully support this proposal. I find this extension very useful for code comprehension and documentation. I often write the instance method signature to help me think about the implementation of the method.

andreasabel avatar May 28 '20 06:05 andreasabel