
May I suggest something for a syntax (as an option, sorry if it's silly or
not related)? I really don't like neither "@" or "#" because they seem too
hacky, meanwhile GHC already has an "accessor" syntax with braces { and },
so, might it be an option to have something like:
```
data Foo = Foo { val :: Int }
data Bar = Bar { foo :: Foo }
main = do
let bar = Bar (Foo 10)
print bar{foo{val}}
let bar' = bar{foo{val}=10}
return ()
```
I think this syntax is 100% understandable for a "newbie". Not sure how is
it related to lenses though.
What do you think?
If the level of complaints I received when I stole (#) for use in lens is
any indication, er.. it is in very wide use. It was by far the most
contentious operator I grabbed. ;)
It seems to me that I'd not be in a hurry to both break existing code and
pay a long term syntactic cost when we have options on the table that don't
require either, the "magic Field module" approach that both Eric and I
appear to have arrived at independently side-steps this issue nicely and
appears to result in a better user experience.
Keep in mind, one source of objections to operator-based sigils is that if
you put an sigil at the start of a lens the tax isn't one character but
two, there is a space you now need to avoid (.#) when chaining these
things. "foo.bar" vs. "#foo . #bar" and the latter will always be uglier.
The `import Field (...)` approach results in users never having to pay more
syntactically than with options they have available to them now, and being
class based is even beneficial to folks who don't use Nikita's records.
-Edward
On Fri, Jan 23, 2015 at 5:47 PM, Greg Weber
If we only add syntax when the language extension is used then we are not clobbering everyone. # is not that common of an operator. I would much rather upset a few people by taking that operator back when they opt-in to turning the extension on than having a worse records implementation.
On Fri, Jan 23, 2015 at 2:23 PM, Edward Kmett
wrote: On Fri, Jan 23, 2015 at 5:06 PM, Adam Gundry
wrote: Thanks for the feedback, Iavor!
On 23/01/15 19:30, Iavor Diatchki wrote:
2. I would propose that we simplify things further, and provide just one class for overloading:
class Field (name :: Symbol) rec rec' field field' | name rec -> field , name rec' -> field' , name rec field' -> rec' , name rec' field -> rec where field :: Functor f => Proxy name -> (field -> f field') -> (rec -> f rec')
I don't think we need to go into "lenses" at all, the `field` method simply provides a functorial update function similar to `mapM`. Of course, one could use the `lens` library to get more functionality but this is entirely up to the programmer.
When the ORF extension is enabled, GHC should simply generate an instance of the class, in a similar way to what the lens library does
3. I like the idea of `#x` desugaring into `field (Proxy :: Proxy "x")`,
but I don't like the concrete symbol choice: - # is a valid operator and a bunch of libraries use it, so it won't be compatible with existing code.
Ah. I didn't realise that, but assumed it was safe behind -XMagicHash. Yes, that's no good.
- @x might be a better choice; then you could write things like: view @x rec set @x 3 rec over @x (+2) rec
This could work, though it has the downside that we've been informally using @ for explicit type application for a long time! Does anyone know what the status of the proposed ExplicitTypeApplication extension is?
I'll confess I've been keen on stealing @foo for the purpose of (Proxy :: Proxy foo) or (Proxy :: Proxy "foo") from the type application stuff for a long time -- primarily because I remain rather dubious about how well the type application stuff can work, once you take a type and it goes through a usage/generalization cycle, the order of the types you can "apply" gets all jumbled up, making type application very difficult to actually use. Proxies on the other hand remain stable. I realize that I'm probably on the losing side of that debate, however. But I think it is fair to say that that little bit of dangling syntax will be a bone that is heavily fought over. ;)
- another nice idea (due to Eric Mertens, aka glguy), which allows us
to avoid additional special syntax is as follows: - instead of using special syntax, reuse the module system - designate a "magic" module name (e.g., GHC.Records) - when the renamer sees a name imported from that module, it "resolves" the name by desugaring it into whatever we want - For example, if `GHC.Records.x` desugars into `field (Proxy :: Proxy "x")`, we could write things like this:
import GHC.Records as R
view R.x rec set R.x 3 rec over R.x (+2) rec
Interesting; I think Edward suggested something similar earlier in this thread. Avoiding a special syntax is a definite advantage, but the need for a qualified name makes composing the resulting lenses a bit tiresome (R.x.R.y.R.z or R.x . R.y . R.z). I suppose one could do
import GHC.Records (x, y, z) import MyModule hiding (x, y, z)
but having to manually hide the selector functions and bring into scope the lenses is also annoying.
In the suggestion I made as a (c) option for how to proceed around field names a few posts back in this thread I was hinting towards having an explicit use of {| foo :: x |} somewhere in the module provide an implicit import of
import Field (foo)
then users can always reference Field.foo explicitly if they don't have such in local scope, and names all share a common source.
Of course this was in the context a Nikita style {| ... |} rather than the ORF { .. }.
If the Nikita records didn't make an accessor, because there's no way for them to really do so, then there'd be nothing to conflict with.
Being able to use import and use them with ORF-style records would just be gravy then. Users would be able to get those out of the box.
-Edward
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs