Created
January 18, 2018 21:04
-
-
Save vendethiel/5b830f94b5cf838e66c61ea629e31d0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[20:57:31] <Ven``> we have (potentially) a lot to discuss. Should we start by bikeshedding, discussing viable implementations, ..? | |
[20:59:05] <rhendric> Not sure those conversations are separable. Implementation should inform design at least somewhat. Maybe we should start with goals? | |
[20:59:20] <Ven``> OK, fair enough. | |
[20:59:37] <rhendric> As in, is this the beginning of an eventual full support of types in Flow and/or TypeScript format? | |
[20:59:46] <rhendric> Is this a stopgap measure to make things a little more usable? | |
[21:00:03] <rhendric> Something else or in between? | |
[21:00:24] <Ven``> Definitely full support. Though not necessarily in the very beginning. | |
[21:00:57] <Ven`> I don't mind if I don't get e.g. object types and class types in the early beginning. | |
[21:01:03] <Ven`> Inference itself would help alleviate that | |
[21:01:31] <rhendric> Ideally, yes. | |
[21:02:01] <Ven`> For now, I want to get types on function args/function returns/let/var/const. | |
[21:02:17] <Ven`> simple types and generics. | |
[21:02:31] <rhendric> But we should also keep an eye on the rest of what we eventually want to support, in that case. | |
[21:02:42] <Ven`> Oh, definitely. | |
[21:02:56] <Ven`> it's tough. the syntax baggage of LS is... quite heavy | |
[21:03:02] <rhendric> Yes, that. | |
[21:03:13] <Ven`> I'd be interested if we could come up with a way to type objects that's not hell to parse. | |
[21:03:22] <rhendric> So. | |
[21:03:26] <Ven`> (and doesn't require to do it all in a @do-ascr in the lexer...) | |
[21:03:43] <rhendric> A lot of these things become much easier if we go full Haskell and separate types from values entirely. | |
[21:04:11] <Ven`> We definitely should, but I don't see much we need to do to get that..? | |
[21:04:30] <rhendric> There are some usability issues with that, clearly, but if we eventually want to support the moving target that is ‘anything that TypeScript/Flow support’, I think that's our best bet. | |
[21:05:18] <rhendric> Not much we need to do, agreed. | |
[21:05:19] <Ven`> What are the issues you're thinking of? | |
[21:05:22] <rhendric> Well, not as much. | |
[21:05:45] <rhendric> When I say separate, I mean no `(a :: A) :: B => a-to-b a`. | |
[21:06:01] <rhendric> Instead `f :: (A) -> B` | |
[21:06:10] <rhendric> `f = (a) -> a-to-b a | |
[21:06:17] <Ven`> OK. So really full Haskell. | |
[21:06:35] <rhendric> Yeah. | |
[21:06:38] <Ven`> it makes some stuff neater. It makes some stuff harder. | |
[21:06:43] <Ven`> How do you spell a let with types? | |
[21:06:48] <Ven`> How do you spell a typed instance variable? | |
[21:06:58] <Ven`> How do you spell a ES6-class-like method? | |
[21:08:02] <rhendric> let: not sure if necessary? | |
[21:08:17] <rhendric> But if necessary, ascription inside the let block, I guess. | |
[21:09:03] <rhendric> Maybe TypeScript isn't as good as Flow is in letting stuff like that be implicitly typed. | |
[21:09:41] <rhendric> typed instance variable: inside an LS class, just add a declaration. | |
[21:09:47] <Ven`> I think it's not as good, but I'd rather target TS than Flow, TBH. | |
[21:09:53] <Ven`> It seems like the community picked a side... | |
[21:10:06] <Ven`> (Windows support played a huge part there IMHO) | |
[21:11:01] <rhendric> I think in communities that use React at least, Flow is still dominant. | |
[21:11:27] <rhendric> Possibly others, although it's hard to see past the bias of my own experience. | |
[21:11:39] <Ven`> Same for my echo chamber :-). | |
[21:12:58] <rhendric> Anyway, you think TypeScript would require a function declared and used only once to have explicit types on its parameters to be typed inside? | |
[21:14:52] <Ven`> https://imgur.com/a/felN9 | |
[21:15:00] <Ven`> yup. | |
[21:15:20] <rhendric> Gross. | |
[21:15:36] <Ven`> they probably do that for "backwards compat reasons" | |
[21:15:56] <rhendric> Probably. | |
[21:16:10] <rhendric> It makes sense given the gestalt I have of TS philosophy, but still. | |
[21:16:36] <rhendric> It makes our work really difficult, because what if there are other instances of LS constructing code that TS would need to have annotated? | |
[21:17:15] <Ven`> I think it does objects correctly. | |
[21:17:33] <Ven`> though we need a way to write union&intersection types. that goes for both flow & TS | |
[21:17:43] <Ven`> (I think we both agree Flow is superior to TS, it's just about the size of the community | |
[21:17:46] <Ven`> ) | |
[21:17:47] <rhendric> What about LS's util functions? | |
[21:17:55] <rhendric> Will things like in$ need to be annotated? | |
[21:18:23] <Ven`> Tough call. Probably? This is where flow comments would prove useful, I suppose... | |
[21:18:33] Ven` doesn't want to introduce yet another compiler flag like --types | |
[21:18:43] rhendric doesn't either | |
[21:19:15] <rhendric> Times like this, that babel backend would really come in handy. | |
[21:19:29] <Ven`> Yup, I was really thinking the same :-P. | |
[21:20:16] <Ven`> Having a sane AST and a sane codegen would help as well | |
[21:20:19] Ven` mourns CSR for a bit | |
[21:20:42] <Ven`> I havn't looked at livescript-next too much, actually. Anyway, that's enough disgression. | |
[21:21:02] <Ven`> so, I'll do some digging to see if TS is able to infer anything at all. | |
[21:21:32] <Ven`> https://www.typescriptlang.org/docs/handbook/type-inference.html seems like it does bottom-up type derivation | |
[21:21:37] <Ven`> but no further "type inference" | |
[21:21:54] <Ven`> That's an issue with your proposal, I think, I don't really want to have to name all the functions I'm going to type. | |
[21:22:07] <Ven`> I mean, an issue with the Haskell-style declare-then-define | |
[21:22:25] <rhendric> Yeah. Like I said, usability issues. | |
[21:22:39] <rhendric> I know it's less powerful than the alternative. | |
[21:23:10] <rhendric> I'm just not sure the more powerful thing can be made compatible with LiveScript's syntax without creating a messy headache. | |
[21:24:31] <Ven`> "more powerful thing" being? | |
[21:24:51] <rhendric> ‘Mixfix’ type annotations. | |
[21:25:06] <Ven`> you mean infix :: or @: ? | |
[21:25:11] <rhendric> Yeah. | |
[21:25:34] <rhendric> Along with whatever we do for return types for functions. | |
[21:29:50] <Ven`> So you'd propose to still do it the Haskell way and all? | |
[21:32:03] <Ven`> I don't think that way would make the feature that useful to me. | |
[21:32:23] <Ven`> ....unless we go totally crazy and re-introduce `where` and allow type annotations there :P. Full haskell indeed. | |
[21:32:47] <rhendric> Ha, yeah, that seems off the table. | |
[21:32:55] Ven` wouldn't be against reintroducing where, but that's another issue altogether! | |
[21:32:58] <rhendric> If it's not useful, then no point in trying to do it that way. | |
[21:33:23] <Ven`> well, the haskell way would mean that for e.g. every .map I want to write needs a declared function. | |
[21:33:36] <Ven`> That's a verbosity LS has not used me to :P. | |
[21:34:13] <rhendric> The prospect of `complicated LS expression with (complicated destructuring :: complicated type) :: more complicated type -> function body` freaks me out a little. | |
[21:34:43] <Ven`> no, no, I think that's a non-goal. | |
[21:34:59] <rhendric> Yeah, I was operating on the assumption that little map one-liners could be inferred by the type checker, but I guess that won't work for TS. | |
[21:35:01] <Ven`> You don't write `{a :: number} = x`. That's one case where both TS and Flow do the right thing. | |
[21:35:49] <Ven`> https://imgur.com/a/ArmSM | |
[21:35:57] <Ven`> (it doesn't show b's type because it's not selected) | |
[21:36:34] <rhendric> So: let's annotate `objs.map(({ a, b }) -> (x) -> a*x + b)` | |
[21:36:36] <Ven`> actually this is a better example: https://imgur.com/a/KI0wI | |
[21:37:15] <Ven`> Proposed: | |
[21:38:28] <Ven`> https://gist.github.com/vendethiel/49ff86793d796c535e45de75ddc58f62 | |
[21:40:34] <rhendric> For that matter, maybe: | |
[21:41:03] <Ven`> (we don't do anything with `type`, we just translate it to an alias. Hopefully those look the same for TS and Flow....) | |
[21:41:12] <rhendric> type f = Function { a :: number, b :: number }, Function number, number | |
[21:41:36] <rhendric> objs.map(({ a, b }) -> (x) -> a*x + b :: f) | |
[21:42:08] <rhendric> And *then* we can replace Function with -> without conflict :-). | |
[21:42:09] <Ven`> uhhh... parsing f there to be the whole function's type is gonna prove **difficult** | |
[21:42:16] <rhendric> Is it? | |
[21:42:22] <rhendric> Just give :: very low precedence? | |
[21:42:38] <Ven`> precedence isn't gonna matter, we added parentheses there. | |
[21:43:08] <Ven`> (also my progress on :: was further stalled because <<< might be somehwere rewritten to ::, I didn't check again) | |
[21:43:41] <rhendric> (Whatever, mentally replacing :: with @: if necessary isn't a big deal I don't think.) | |
[21:43:52] <Ven`> (I just wanted to make a comment about it) | |
[21:43:57] <rhendric> I don't understand what the problem is still. | |
[21:44:12] <Ven`> The problem for a :: there? | |
[21:44:54] <rhendric> I guess? Is that the problem? | |
[21:45:40] <Ven`> first off, it potentially conflicts with casts. Second, it's not clear which function it applies to. Third: we rewrite `(x) -> (y) -> x + y :: f` to `(x) -> ((y) -> (x + y.prototype(f)))` before the parser ever sees it. | |
[21:45:46] <Ven`> So there's nothing about "precedence" etc to be applied. | |
[21:47:22] <rhendric> That rewrite can be made to stop at ASCR tokens, can't it? | |
[21:47:26] <rhendric> What's the cast conflict? | |
[21:47:30] <Ven`> also I don't see how we'd compile your code, outside of a cast? | |
[21:47:46] <Ven`> the cast conflict: well, we might want a + b :: Int to mean `(int)(a + b)` | |
[21:48:03] <Ven`> The rewrite can be made to stop at ASCR tokens, but then how do you type only the inner function? | |
[21:48:06] <rhendric> Oh, does TS allow that? | |
[21:48:21] <Ven`> I think so. At least there's a "x as Type", swift-like | |
[21:48:27] <Ven`> (or c# like rather) | |
[21:48:32] <rhendric> With Flow, you can only (upcast? downcast? Whichever one is the safe one) that way. | |
[21:48:47] <Ven`> it depends on the type's variance :-) | |
[21:49:16] <rhendric> You type only the inner function by adding parentheses, if you want. | |
[21:50:25] <Ven`> it still seems to me like we lose reading comprehension there. By putting the important infos on the wayside | |
[21:50:46] <rhendric> A little, sure. | |
[21:51:11] <rhendric> But your way, the arrow rewriter in the lexer has to jump over the Function Int Int before it gets to the PARAM( rewriting it needs to do. | |
[21:51:35] <Ven`> that's not my way, that's your way ;-0 | |
[21:51:38] <Ven`> my way is with []. | |
[21:51:51] <rhendric> Ooookay, sure. | |
[21:52:19] <rhendric> So if we go full Scala, we now have two different ‘expression’ languages in LiveScript. | |
[21:52:54] <rhendric> And how do you notate tuples? A `Tuple` special type constructor like `Function`? | |
[21:53:21] <Ven`> TS doesn't have tuples | |
[21:53:33] <Ven`> oh, they do actually | |
[21:53:57] <Ven`> they write [a, b], huh. How is it in Flow? | |
[21:54:01] <rhendric> Same. | |
[21:54:13] <Ven`> I'm surprised they didn't go for the "obvious" (a, b) | |
[21:54:15] <Ven`> Okay. | |
[21:55:01] <rhendric> I have to go in a few minutes; is there a nice place to conclude this? | |
[21:56:20] <Ven`> Well, from reading this, apparently not | |
[21:56:36] <rhendric> I think we've agreed that both TS and Flow should be targets; that we want to support everything possible eventually; and that a pure Haskell-like approach isn't viable (but maybe something that is almost that approach with some very simple infix :: support is?). | |
[21:56:43] <rhendric> Other than that, a lot of unknowns and maybes. | |
[21:57:34] <Ven`> https://gist.github.com/vendethiel/ae15873a428627de640a32cdefe83ce2 is really not that bad. | |
[21:57:43] <Ven`> We could have :: (Int -> Int), if we force parentheses to be used. | |
[21:57:47] <Ven`> I think that's totally viable | |
[21:58:02] <Ven`> ... but we need to make -> lookbehind more complex, yet again. | |
[21:58:19] Ven` didn't realize it had already been an hour... | |
[21:58:59] <rhendric> I personally am willing to give up a fair amount of visual appeal in order to have the lexer not get more complex. | |
[21:59:34] <Ven`> actually no, I'm totally wrong. | |
[21:59:41] <Ven`> @parameters doesn't need to be made any more complex. | |
[21:59:55] <Ven`> We also have the option of ASCR doing some parsing. Like a sub-language, much like literals or regexes. | |
[22:00:04] <rhendric> I have to go. | |
[22:00:14] <rhendric> I'll happily review any further POCs you want to invest in. | |
[22:00:23] <Ven`> I suppose on the issue tracker | |
[22:00:30] <rhendric> You've heard the objections I anticipate making. | |
[22:00:48] <Ven`> aye. | |
[22:01:02] <rhendric> Okay, good hunting! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment