Simon, there are times when a function has to be generalized to be made polymorphic recursive. Perhaps the method takes an argument of type x (not a class parameter), but to call itself, it needs to be able to take types x, T x, T (T x), etc. That additional polymorphism can be introduced in the instance signature. The alternative is to introduce a helper function with extra polymorphism.
On Tue, Aug 10, 2021, 5:15 AM Simon Peyton Jones <simo...@microsoft.com> wrote: > AntC, > > > > I think you see why the instance sig must be at least as polymorphic than > the instantiated signature from the class – because that’s what the client > is going to expect. We are building a record of functions, and they must > conform to the class signature. > > > > I agree with David’s (1) and (2) reasons, but not with (3) or (4), neither > of which I quite understand. > > > > There is no compelling reason to make the instance signature *more* > polymorphic – that is, doing so does not increase expressiveness. But it > might make a briefer, more comprehensible type for the reader. The only > alternative would be to insist that the two types are the same, a > completely redundant test, but one you might conceivably want on stylistic > grounds. > > > > All in all, no big deal. Instance signature are a convenience, never a > necessity. > > > > If you would like to offer a patch for the user manual to explain this > better, that would be great. > > > > Simon > > > > *From:* Glasgow-haskell-users <glasgow-haskell-users-boun...@haskell.org> *On > Behalf Of *David Feuer > *Sent:* 08 August 2021 09:37 > *To:* Anthony Clayden <anthony.d.clay...@gmail.com> > *Cc:* GHC users <glasgow-haskell-users@haskell.org> > *Subject:* Re: InstanceSigs -- rationale for the "must be more > polymorphic than" > > > > To the best of my knowledge, `InstanceSigs` are never strictly necessary. > They can, however, be useful for at least four purposes: > > > > 1. To provide a compiler-checked reminder of the type. > > 2. To bind type variables with `ScopedTypeVariables`. > > 3. To generalize the type so you can use polymorphic recursion. > > 4. To enhance parametricitry/polymorphism for internal documentation > purposes. > > > > The third reason is probably the main technical one to allow a more > general signature, but the fourth is likely helpful too. > > > > On Sun, Aug 8, 2021, 3:04 AM Anthony Clayden <anthony.d.clay...@gmail.com> > wrote: > > I can't help but feel InstanceSigs are either superfluous or upside-down. > It's this bit in the User Guide: > > > > > The type signature in the instance declaration must be > > > more polymorphic than (or the same as) the one in the class declaration, > > > instantiated with the instance type. > > > > Usually if you give a signature, it must be _less_ polymorphic (or the > same as) the type inferred from the term: > > > > > lessPolyPlus :: Integral a => a -> a -> a > > > lessPolyPlus x y = x + y > > > > Or > > > > > lessPolyPlus (x :: a) y = x + y :: Integral a => a > > > > The examples in the User Guide aren't helping: you could just drop the > InstanceSigs, and all is well-typed. (Even the example alleging to use > -XScopedTypeVariables in a where sub-decl: you could just put random `xs :: > [b]` without scoping `b`.) > > > > Dropping the Sigs altogether works because the type from the class decl, > suitably instantiated, is less polymorphic than inferred from the term. IOW > the suitably instantiated type restricts what would otherwise be inferred. > Situation normal. > > > > I suppose it might be helpful to give an explicit InstanceSig as 'belt and > braces' for the instantiated -- possibly because the instantiation is hard > to figure out; possibly because you want to use -XScopedTypeVariables > within a where-bound sub-decl, as an extra piece of string. > > > > I can see you mustn't make the InstanceSig _less_ polymorphic than the > suitably instantiated. > > > > But the docos don't give any example where it's essential to provide an > InstanceSig _and_ make it strictly more polymorphic. Here all the sigs and > annotations are just superfluous: > > > > > maxPolyPlus :: Num a => a -> a -> a > > maxPolyPlus = (+) > > > > > class C a where foo :: a -> T a > > instance Integral a => C a where > > foo :: Num a => a -> T a > > foo (x :: a) = MkT (maxPolyPlus x x :: Num a => a) > > > > Is there a persuasive example (to put in the User Guide)? > > > > AntC > > > > _______________________________________________ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users > <https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fglasgow-haskell-users&data=04%7C01%7Csimonpj%40microsoft.com%7C51928cea45a84d24d62508d95a47ba3c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637640086425578886%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=qY9jOKGv3RIFPCuVT%2FZIBfaBBofcm6p7PG3yfq%2FJRiM%3D&reserved=0> > >
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users