haskell / rfcs

This repo is archived, consider using https://github.com/ghc-proposals/ghc-proposals instead
98 stars 17 forks source link

Enable InstanceSig by default #13

Open nomeata opened 8 years ago

nomeata commented 8 years ago

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

zenzike commented 8 years ago

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.

goldfirere commented 8 years ago

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.

nomeata commented 8 years ago

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?

goldfirere commented 8 years ago

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

thoughtpolice commented 8 years ago

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).

nomeata commented 8 years ago

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

mitchellwrosen commented 7 years ago

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.

nomeata commented 7 years ago

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?

goldfirere commented 7 years ago

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.)

mitchellwrosen commented 7 years ago

@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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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!

goldfirere commented 7 years ago

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!

andreasabel commented 4 years ago

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.