That's an extremely limited point of view. Just because Haskell allows precise
specification does not mean it is impossible to disallow loose specification. In fact that's one of the strongest values of Haskell's type system. For example you can overconstrain your head function
head :: [Int] -> Int
But you can also just leave out the type signature all together to let the type
checker figure out the most generic type. You can have your cake and eat it too.
You can even almost do what I want with partial type signatures. Just sprinkle
it everywhere inside your constraints. GHC will automatically pick the right constraints.
At the call site you actually care for the definition you can not use the
partial type signature. The great disadvantage of this is that you now introduce
ANY constraints into your type signature and you lose your types as documentation.
But that doesn't have to be
You could have a constraint with something like `UseMonadSubset (...)` which
works almost like partial type signature. GHC should infer 0 or more of the monads
insde `UseMonadSubset` as the actuall constraint. `
Then you could write something like:
fibonacci :: UseMyMonadSubset m => m Int
fibonacci = -- Uses only MonadState (Int, Int, Int)
-- Type checks because type checker can see fibonacci ONLY uses MonadState
foo :: MonadState (Int, Int, Int) m => Int
foo = fibonacci
bar :: UseMonadSubset m => Int
bar = fibonacci
Which allows for precise specification if you want to and if you don't you let the
type checker figure it out. You may even be able to implement this as GHC type
checker plugin.
It's an interesting idea but I can't say I feel that would solve a problem I've ever had. In fact, I always completely annotate top-level definitions with their types. I never want them inferred. And I've never felt it too burdensome to fix up a call stack when adding a new effect. But if you consider that a weakness of Haskell then so be it!
You can even almost do what I want with partial type signatures. Just sprinkle it everywhere inside your constraints. GHC will automatically pick the right constraints. At the call site you actually care for the definition you can not use the partial type signature. The great disadvantage of this is that you now introduce ANY constraints into your type signature and you lose your types as documentation.
But that doesn't have to be
You could have a constraint with something like `UseMonadSubset (...)` which works almost like partial type signature. GHC should infer 0 or more of the monads insde `UseMonadSubset` as the actuall constraint. `
Then you could write something like:
Which allows for precise specification if you want to and if you don't you let the type checker figure it out. You may even be able to implement this as GHC type checker plugin.