@maxigit So at the end of the day this a poll, you can have what ever opinion you like! I just want to make sure we are at least understanding each other, not that we agree necessarily
Why can’t the scoping rules be the same for type and value ?
From my point of view, that is what I am trying to do: fix the rules so they are the same!
That the bit I really don’t get. How is it a problem in practice ? In
(x :: a) = x :: a
, that doesn’t pose a problem to anybody to have to look at the firstx
to understand the secondx
, so why is it a problem for thea
s ???
Let’s step back a bit.
-
When I read the
x
or thea
to the right of the=
, I can no for sure this is a variable use. My brain goes "OK, new variable, better go find out what it refers to, or remember it for when I encounter the binding later. -
When I likewise encounter the
x
to the left of the=
, I likewise can go “OK, found wherex
is defined, I don’t need to keep on looking”. -
When I encounter the
a
to the left of the=
, I can make no such call. Sure, I’ve found something that is of typea
, but I have no idea whata
is — further out there could be other usages, or something that fully constrains it, likea ~ Int
. I have no choice but to keep on searching to learn more abouta
.
Again as @jaror says, scale matter. id (x :: a) = x :: a
is fine, but
f (SomeGadt :: Foo a) (x :: [a]) =
... -- 30 lines!
where
... -- 30 more lines!
x :: Maybe a = ... -- pop quiz, is this `a` a bind or a use?
is a lot harder
So that’s what I don’t like about implicit binding: reading left-to-right/outside-in, it’s alright, but reading right-to-left/inside-out, it’s a lot harder. And most of what I do is reading code that I did not write, random accessing all over the codebase (within modules and between modules). Therefore making reading as easy as possible, even at the expense of a few keystrokes, is very important me.