Hi Hongwei, On Tuesday, March 26, 2019 at 3:22:41 PM UTC+2, gmhwxi wrote: > > Here is a linear version: > > https://pastebin.com/sqXcRhnf > > Also, Command is a linear datatype (i.e., dataviewtype). > > Great! Now, what about boxing, can we do something with boxing? I expect such code, if it's really used in practice, to involve LOTS of these little objects. So it will probably behave badly if every call to a continuation involves a heap allocation... Let us be a bit more resource-conscious, please. :)
I did a similar example a while back where I used some CPS style to get rid of boxing: https://github.com/ashalkhakov/tfc/blob/master/src/SATS/cont.sats Basically we can 'co-opt' the ATS compiler to do all the plumbing. The closure call and its packing is non-uniform but the closure itself is uniform in size, since it's a pointer to the heap: https://github.com/ashalkhakov/tfc/blob/master/test/threads.dats To call a continuation, the return type must be statically known (at both the callee side and the caller side). So maybe we can do something similar here? > > > On Tue, Mar 26, 2019 at 9:02 AM Hongwei Xi <gmh...@gmail.com <javascript:>> > wrote: > >> Nice! >> >> But I am very surprised that this code actually works. >> My understanding is that It works because of a bug in patsopt :) >> >> Basically, runCommand should be implemented as a polymorphic function >> (instead of a function >> template). And 'a:t0ype' should be 'a:type'. >> >> fun runCommand: {a:type} Command(a) -> a >> >> Actually, I think that Command should be a linear type, which should you >> more fun! >> >> On Tue, Mar 26, 2019 at 5:49 AM Artyom Shalkhakov <artyom.s...@gmail.com >> <javascript:>> wrote: >> >>> I've made a gist: >>> >>> https://gist.github.com/ashalkhakov/c3577e97b20020fde31f84447fd1e056 >>> >>> It actually works. It illustrates the basics (sequencing, bind, input >>> and output). Nice. It doesn't have Haskell's "return" though, but that is >>> pretty simple to add (it's something that "creates" IO where there is no IO >>> at all...). >>> >>> The interpreter is using a continuation in the end. I chose this style >>> because the closure-function (i.e. our continuation) can be passed around >>> freely, whereas with a flat unboxed type it is sometimes difficult for the >>> C compiler to figure out the size of the variable. >>> >>> On Tuesday, March 26, 2019 at 10:11:11 AM UTC+2, Artyom Shalkhakov wrote: >>> >>>> Hi Brandon, >>>> >>>> On Friday, March 22, 2019 at 8:49:29 PM UTC+2, Brandon Barker wrote: >>>>> >>>>> Hey Artyom, >>>>> >>>>> Thanks for the very interesting analysis and response. >>>>> >>>>> >>>> Glad you found it useful! >>>> >>>> On Fri, Mar 22, 2019 at 4:06 AM Artyom Shalkhakov < >>>>> artyom.s...@gmail.com> wrote: >>>>> >>>>>> Hi Brandon, >>>>>> >>>>>> This is a very lively discussion, thanks for bringing it up. >>>>>> >>>>>> On Friday, March 22, 2019 at 5:48:07 AM UTC+2, Brandon Barker wrote: >>>>>>> >>>>>>> And for what it's worth, here is an Idris program for haha using >>>>>>> Effects: >>>>>>> >>>>>>> module Main >>>>>>> >>>>>>> >>>>>>> import Effects >>>>>>> import Effect.StdIO >>>>>>> >>>>>>> >>>>>>> hello : Eff () [STDIO] >>>>>>> hello = let ha = StdIO.putStr "ha" in ha *> ha >>>>>>> >>>>>>> >>>>>>> main : IO () >>>>>>> main = run hello >>>>>>> >>>>>>> >>>>>>> >>>>>>> It prints "ha" twice, despite being a strict language. I presume, >>>>>>> but am not sure, this is because the effect time requires it to be >>>>>>> re-evaluated each time. >>>>>>> >>>>>>> >>>>>>> >>>>>> Well, the type of "hello" says that the computation will use the >>>>>> STDIO effect as many times as is necessary. The way the computation is >>>>>> constructed, it is meant to issue commands in a given sequence. >>>>>> >>>>>> One peculiarity of PureScript is that of handling effects via the >>>>>> algebraic effects approach. It's not easy to do in a high-performance >>>>>> way, >>>>>> because you need a call/cc construct present in the language, and >>>>>> moreover >>>>>> a 'multi-shot' one at that (i.e. the continuation *may* be invoked zero, >>>>>> once or more times by the effect interpreter). In ATS a simpler way is >>>>>> to >>>>>> use template functions to define effects differently (e.g. during >>>>>> testing >>>>>> and during the actual execution) -- it's constrained compared to the >>>>>> call/cc for sure, but then you don't have to pay the price of the >>>>>> call/cc >>>>>> plumbing. Another thing about PureScript is that it uses row types to >>>>>> track >>>>>> the set of effects that a given Eff computation may involve during its >>>>>> evaluation. >>>>>> >>>>> >>>>> Not that it will invalidate anything you just said, but the above code >>>>> was Idris, but they may be similar in this regard (not sure). I need to >>>>> look into call/cc more at some point - not very familiar with this idea. >>>>> But I like where you are going with templates in ATS! >>>>> >>>> >>>> >>>> Haha, right! I mixed them up. I do remember reading about effects in >>>> both languages! And I think they are pretty similar, except in Idris, you >>>> have a type-level list of effects, whereas in PureScript, it is instead a >>>> row of effects. So, pretty similar from the POV of using it. I think. :) >>>> >>>> >>>>> >>>>>> So in short, if we view the programs as creating commands, and then >>>>>> some kind of external interpreter that executes them, then it all >>>>>> matches >>>>>> up. The programs might be quite pure and non-side-effecting (except for >>>>>> non-termination aka infinite looping runtime exceptions), the >>>>>> interpreter >>>>>> will perform the effects. Here's a pseudocode for the interpreter: >>>>>> >>>>>> // the command sub-language >>>>>> datatype Command = Print of string | Nop | Seq of (command, command) >>>>>> extern >>>>>> fun runCommand (c:Command): void >>>>>> extern >>>>>> fun seq (c:Command, Command): Command >>>>>> extern >>>>>> fun cprint (s:string): Command >>>>>> implement >>>>>> seq (c1, c2) = Seq (c1, c2) >>>>>> implement >>>>>> cprint (s) = Print s >>>>>> // the interpreter itself >>>>>> implement >>>>>> runCommand (c) = case+ c of Nop => (*done!*) | Print s => print (s) | >>>>>> Seq (c1, c2) => (runCommand(c1); runCommand(c2)) >>>>>> >>>>>> Now let's assume the Command is abstract for the rest of the program >>>>>> (and only the runCommand, seq and print are exposed). We can now write: >>>>>> >>>>>> val hello = let val h = cprint "hi" in seq (h, h) end // here. twice >>>>>> the effect! >>>>>> implement >>>>>> main0 () = runCommand hello >>>>>> >>>>>> The "hello" itself is free of side-effects (or so it seems to me!). >>>>>> We might need to lazily evaluate stuff here (e.g. to enable looping, >>>>>> where >>>>>> you need to give the interpreter the chance to run side-by-side with >>>>>> your >>>>>> expression). Or we need a more poweful "seq" (i.e. the Haskell's "bind" >>>>>> operator for stitching together the commands such that the left-hand >>>>>> side >>>>>> has to be evaluated to a value that is then fed to the right-hand side >>>>>> -- >>>>>> i.e. incrementally built-up as it's being evaluated by the interpeter). >>>>>> >>>>>> In Haskell, the type Command is termed "IO" (with an additional type >>>>>> parameter to signify the result type of the command) and the interpreter >>>>>> is >>>>>> somewhere in the runtime system. >>>>>> >>>>> >>>>> Nice to see that the basis of an interpreter can be created so easily! >>>>> I guess to make it feasible to program in, in addition to the issues you >>>>> just mentioned, some primitive standard library functions would need to >>>>> be >>>>> wrapped up as 'Command' functions just as you did with cprint; another >>>>> way >>>>> to do this might be to ascribe certain effect types to these primitives >>>>> using e.g praxi. Functions that build on these primitives could then >>>>> accumulate effects - perhaps some effects could even be consumed, but not >>>>> sure. Also not sure how the interpreter would deal with some values have >>>>> more than one effect type: Haskell seems to use the idea of monad >>>>> transformers to get around this but I do not find it particularly >>>>> satisfying so far >>>>> >>>> >>>> In Haskell there exists special support for the IO monad in the runtime >>>> and in the compiler; without such support I don't think it will be >>>> feasible >>>> to program in this way (since we will have to pay the price for the >>>> construction of terms even in the simplest of cases!). >>>> >>>>> >>>>> Still need to look into effects and how to encode different effect >>>>> types - I seem to recall ATS actually had build in support for effects at >>>>> the type level at some point. >>>>> >>>> >>>> Well, in my post I was talking mostly about algebraic effect handlers, >>>> and in ATS we have effect types. The former I'm interested in mostly >>>> because of modular testing. The latter, I think, is used mostly for >>>> tracking the dynamic terms that can be safely erased from the program with >>>> no change to said program's behavior. >>>> >>>> >>>>> Do you have or plan on having a repo to play around with this idea? If >>>>> not I may try to start one (at some point). >>>>> >>>> >>>> Well, I'll post it as a gist on github. I think there does exist a >>>> connection between the algebraic effect handlers and function templates >>>> that I would like to pursue, but I'm short on time. >>>> >>>> >>>>> >>>>> >>>>>> >>>>>> >>>>>>> On Thursday, March 21, 2019 at 11:33:35 PM UTC-4, Brandon Barker >>>>>>> wrote: >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Thu, Mar 21, 2019 at 8:18 PM gmhwxi <gmh...@gmail.com> wrote: >>>>>>>> >>>>>>>>> >>>>>>>>> One can definitely build a monad-based library to support IO: >>>>>>>>> >>>>>>>>> absvtype IO(a:vt@ype) = ptr >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> If really using monads, would it also be reasonable to do (or >>>>>>>> ideally start at Functor and then build up to Monad): >>>>>>>> >>>>>>>> absvtype Monad(a:vt@ype) = ptr >>>>>>>> >>>>>>>> somewhat as discussed at >>>>>>>> https://groups.google.com/forum/m/#!msg/ats-lang-users/gLiMU29C77c/sIjtqzmCBAAJ >>>>>>>> >>>>>>>> >>>>>>>>> The problem with IO monad is that it is so broad. With linear >>>>>>>>> types, >>>>>>>>> a programmer can specify a lot more precisely. >>>>>>>>> >>>>>>>>> I agree. But my limited and slowly changing experience suggests >>>>>>>> that IO is a good starting point to help ensure purity in the rest of >>>>>>>> the >>>>>>>> code that doesn't have effects; IO can typically be refined later to >>>>>>>> different types of Effects, I suppose. >>>>>>>> >>>>>>>> >>>>>>>>> >>is that ATS doesn't (by default?) model an IO effect. >>>>>>>>> >>>>>>>>> No, it doesn't if you use the default library. But nothing >>>>>>>>> prevents you >>>>>>>>> from tracking IO effects in ATS. >>>>>>>>> >>>>>>>> >>>>>>>> So in this case, one would create an alternative 'main' that must >>>>>>>> be composed of IO values. But what is to stop somewhat from calling >>>>>>>> print >>>>>>>> in a function returning an IO, for instance? Thus violating the IO >>>>>>>> contract. >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>> In the book you mentioned in your message, I was really thinking of >>>>>>>>> views for specifying memory layouts. With linear views, a >>>>>>>>> programmer >>>>>>>>> can be very precise in describing what memory a function can >>>>>>>>> access/update. >>>>>>>>> Compared to state monads, this kind of precision is unmatched. >>>>>>>>> >>>>>>>> >>>>>>>> Agreed. Maybe a separate effect type for STDIO, STDIN, etc would be >>>>>>>> a better starting point. Even in Haskell, I've seen some authors frown >>>>>>>> on >>>>>>>> State since it is, in their view, a bit dishonest and not much better >>>>>>>> htan >>>>>>>> IO (or maybe not better at all; see "false purity" at >>>>>>>> https://www.fpcomplete.com/blog/2017/06/readert-design-pattern). >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>> On Thursday, March 21, 2019 at 1:28:42 PM UTC-4, Brandon Barker >>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Thursday, March 21, 2019 at 9:30:40 AM UTC-4, Brandon Barker >>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>> Hi Artyom, >>>>>>>>>>> >>>>>>>>>>> I'm also grappling with the issue of RT in this case as I'd so >>>>>>>>>>> far only thought about it in terms of function calls, but what you >>>>>>>>>>> and >>>>>>>>>>> Vanessa say helped me to understand the issue. Though I haven't >>>>>>>>>>> managed to >>>>>>>>>>> get ATS to have the same behavior as OCaml in the "let expression" >>>>>>>>>>> above, I >>>>>>>>>>> suspect it is possible. The key phrase here seems to be >>>>>>>>>>> "side-effecting >>>>>>>>>>> expression", and relates to the fact that functions in ATS can >>>>>>>>>>> perform side >>>>>>>>>>> effects without having any effect type or IO monad ascribed to the >>>>>>>>>>> value >>>>>>>>>>> (again, iirc). >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Well, maybe that isn't the real key - the real key, I now think, >>>>>>>>>> is that ATS doesn't (by default?) model an IO effect. In section 6.9 >>>>>>>>>> of >>>>>>>>>> http://ats-lang.sourceforge.net/DOCUMENT/INT2PROGINATS/PDF/main.pdf >>>>>>>>>> it is mentioned that using both linear and dependent types may be >>>>>>>>>> used to >>>>>>>>>> do this, though I think the suggestion here is for more than >>>>>>>>>> printing to >>>>>>>>>> e.g. STDOUT. >>>>>>>>>> >>>>>>>>>> If anyone has looked at modeling/enforcing an IO-like effect type >>>>>>>>>> in ATS, I'd be interested to see it. >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Perhaps tonight I should try out the same in Idris or >>>>>>>>>>> PureScript, which are not lazily evaluated by default but do use >>>>>>>>>>> IO, to get >>>>>>>>>>> a better understanding. >>>>>>>>>>> >>>>>>>>>>> On Thursday, March 21, 2019 at 3:17:46 AM UTC-4, Artyom >>>>>>>>>>> Shalkhakov wrote: >>>>>>>>>>>> >>>>>>>>>>>> Hi Brandon, >>>>>>>>>>>> >>>>>>>>>>>> Admittedly I don't really understand what RT is, but from what >>>>>>>>>>>> I understand, in Haskell the expression like [print "ha"] is >>>>>>>>>>>> basically a >>>>>>>>>>>> command to the top-level interpreter (which is the language >>>>>>>>>>>> runtime) to >>>>>>>>>>>> perform an effect on the console (moreover, it will be evaluated >>>>>>>>>>>> on >>>>>>>>>>>> as-needed basis). Moreover, the ";" is itself another comand, the >>>>>>>>>>>> explicit >>>>>>>>>>>> sequencing command, the meaning of which is "perform the left-hand >>>>>>>>>>>> side >>>>>>>>>>>> effects, then perform the right-hand side effects". Such a command >>>>>>>>>>>> is a >>>>>>>>>>>> value, so it can be passed as a value and reused as many times as >>>>>>>>>>>> is >>>>>>>>>>>> necessary. In ATS, the expression like [print "ha"] evaluates >>>>>>>>>>>> right there >>>>>>>>>>>> to a void/"no value", and the ";" is also NOT a value at all, but >>>>>>>>>>>> rather a >>>>>>>>>>>> "shortcut" syntax to a "let-in-end" form. >>>>>>>>>>>> >>>>>>>>>>>> I like to imagine an interpreter that sits in the Haskell's >>>>>>>>>>>> runtime. Values of IO type are commands to this interpreter. >>>>>>>>>>>> Typical >>>>>>>>>>>> Haskell IO-based programs are building up these commands as they >>>>>>>>>>>> are being >>>>>>>>>>>> evaluated by the runtime. The runtime starts evaluation at the >>>>>>>>>>>> "main" >>>>>>>>>>>> expression defined by the programmer. >>>>>>>>>>>> >>>>>>>>>>>> чт, 21 мар. 2019 г. в 03:45, Brandon Barker < >>>>>>>>>>>> brandon...@gmail.com>: >>>>>>>>>>>> >>>>>>>>>>>>> I'm a little rusty, so can't come up with many good examples. >>>>>>>>>>>>> >>>>>>>>>>>>> Apparently it is possible to do something like this in OCaml: >>>>>>>>>>>>> >>>>>>>>>>>>> implement >>>>>>>>>>>>> main0 () = { >>>>>>>>>>>>> val () = let >>>>>>>>>>>>> val ha = print("ha") >>>>>>>>>>>>> in >>>>>>>>>>>>> (ha; ha) // How to get two ha's here? >>>>>>>>>>>>> end >>>>>>>>>>>>> } >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> After running the program, you would only see one "ha", which >>>>>>>>>>>>> violates RT. >>>>>>>>>>>>> >>>>>>>>>>>>> However, ATS doesn't seem to allow a sequence expression in >>>>>>>>>>>>> the "in" position of a let expression, as this doesn't compile. >>>>>>>>>>>>> Admittedly >>>>>>>>>>>>> I'm just trying to see if ATS2 doesn't have RT in this particular >>>>>>>>>>>>> case, but >>>>>>>>>>>>> it would also be good to know about the sequence expressions here. >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>>>> Google Groups "ats-lang-users" group. >>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>>>> it, send an email to ats-lang-user...@googlegroups.com. >>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/5eba6b86-4146-4ba2-a87f-f8c511d902f0%40googlegroups.com >>>>>>>>>>>>> >>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/5eba6b86-4146-4ba2-a87f-f8c511d902f0%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>> . >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Cheers, >>>>>>>>>>>> Artyom Shalkhakov >>>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "ats-lang-users" group. >>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>> send an email to ats-lang-user...@googlegroups.com. >>>>>>>>> To post to this group, send email to ats-lan...@googlegroups.com. >>>>>>>>> Visit this group at https://groups.google.com/group/ats-lang-users >>>>>>>>> . >>>>>>>>> To view this discussion on the web visit >>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/3d13aac1-2f28-47af-afbd-6d9eced901db%40googlegroups.com >>>>>>>>> >>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/3d13aac1-2f28-47af-afbd-6d9eced901db%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>> . >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> Brandon Barker >>>>>>>> brandon...@gmail.com >>>>>>>> >>>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "ats-lang-users" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to ats-lang-user...@googlegroups.com. >>>>>> To post to this group, send email to ats-lan...@googlegroups.com. >>>>>> Visit this group at https://groups.google.com/group/ats-lang-users. >>>>>> To view this discussion on the web visit >>>>>> https://groups.google.com/d/msgid/ats-lang-users/9ff2fb00-6790-4541-9bc0-0a949a0c46e3%40googlegroups.com >>>>>> >>>>>> <https://groups.google.com/d/msgid/ats-lang-users/9ff2fb00-6790-4541-9bc0-0a949a0c46e3%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>> . >>>>>> >>>>> >>>>> >>>>> -- >>>>> Brandon Barker >>>>> brandon...@gmail.com >>>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "ats-lang-users" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to ats-lang-user...@googlegroups.com <javascript:>. >>> To post to this group, send email to ats-lan...@googlegroups.com >>> <javascript:>. >>> Visit this group at https://groups.google.com/group/ats-lang-users. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/ats-lang-users/73270adc-4327-470b-b900-ae20e3b36cea%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/ats-lang-users/73270adc-4327-470b-b900-ae20e3b36cea%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- You received this message because you are subscribed to the Google Groups "ats-lang-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to ats-lang-users+unsubscr...@googlegroups.com. To post to this group, send email to ats-lang-users@googlegroups.com. Visit this group at https://groups.google.com/group/ats-lang-users. To view this discussion on the web visit https://groups.google.com/d/msgid/ats-lang-users/fd79538d-97ac-4f54-b62d-ceeb08794036%40googlegroups.com.