With InstanceSignatures, I can give a signature for a method within an instance decl.
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.
I can see from this answer that the type part of the sig can't be more specific; but why couldn't you add extra constraints? After all you can put constraints on the instance decl that will make the instance more specific than "the class declaration, instantiated with the instance type".
Addit: (In response to the first couple of comments.) To explain "you can put constraints on the instance decl ... instance more specific": the OVERLAPPABLE instance head here alleges it provides addNat for all types a, b, c. But it doesn't: it only provides if a is of the form SNat a', c is of the form SNat c', etc. I'm asking why I can't similarly restrict the types at the method level?
For example [adapted from Hughes 1999] (more realistically this could be a BST/Rose tree, etc):
data AscList a = AscList [a] -- ascending list
instance Functor AscList where -- constructor class
fmap f (AscList xs) = AscList $ sort $ fmap f xs
-- :: Ord b => (a -> b) -> AscList a -> AscList b -- inferred
Without an instance signature GHC complains no instance for (Ord b). With the signature GHC complains the instantiated sig from the class is more polymorphic than the one given.
This (excellent) answer explains the machinery in the instance dictionary. I can see the entry in the dictionary for the method has a type set from the number of constraints for the method (if any) in the class decl. There's no room to put an extra dictionary/parameter for the method.
That seems merely that the implementation didn't foresee a need. Is there a deeper/more theory-based reason against?
(BTW I'm not ever-so convinced by Hughes' approach: that would want both Ord a => WFT(AscList a) and Ord b => WFT(AscList b). But there's no need to require the incoming (AscList a) is ascending. Other constructor classes for AscList perhaps don't need an Ord constraint anywhere.)
AscList's argument beOrd. - bipllFis a functor iff it providesfmapfor all typesaandb. So it's all-or-nothing, eitherFis a functor or it is not (fmapdoes not work in at least one case). This would be different if we had a functor class likeclass Functor' f a b where fmap' :: (a->b)->f a->f bwherea,bare indices of the class, hence can be constrained in instances. In the libraries there are some variants like this but they are not frequently used in practice. - chiFunctorinstance violates the lawfmap id == id. (id (AscList [3,2,1]) == AscList [3,2,1], butfmap id (AscList [3,2,1]) == AscList [1,2,3].) (Though you can get away with it if you ensure that anAscListvalue can only be created with a smart constructor prevents an unsorted list from being created in the first place.) - chepnerWFT (AscList a)as proxy saying the incoming list is sorted. Then the law still holds. - AntCfmap (f.g) == fmap f . fmap g. Iffmap greorders the list,fis applied to different elements than iff.gwere used directly. - chepner