On Tuesday, March 26, 2019 at 4:07:38 PM UTC+2, gmhwxi wrote: > > A "standard" solution is to use call-by-reference: > > extern > fun > runCommand > {a:vt@ype} > (c:Command(a:vt@ype), &a? >> a): void > > I think we covered this a few months back when Chris asked about it. This finally reminded me of that discussion.
> datavtype > Command(vt@ype) = > | Nop(unit) > | Read(string) > | Print(unit) of string > | Seq(unit) of (Command(unit), Command(unit)) > | {a,b:vtype} Bind(b) of (Command(a), a?, (&a >> a?) -<cloptr1> > Command(b)) > Did you mean to use vtype in {a,b:vtype} here? Or not? > This is a bit more involved but only an implementer like you (not user) > needs to deal with it :) > Hmmm. A sane approach to dependent types is when the user needs none of dependent types to get things going. :) > > > On Tue, Mar 26, 2019 at 10:01 AM Artyom Shalkhakov <artyom.s...@gmail.com > <javascript:>> wrote: > >> On Tuesday, March 26, 2019 at 3:55:47 PM UTC+2, gmhwxi wrote: >>> >>> >> Now, what about boxing, can we do something with boxing? >>> >>> Do you mean that you want to have 'a:t@ype' instead of 'a:type'? >>> >>> >> Yes. I think any use of 'bind' is highly discouraged if we have 'a:type' >> restriction (e.g. want to return an int from an effectful function -- sure, >> but use heap for that...). >> >> >>> On Tue, Mar 26, 2019 at 9:36 AM Artyom Shalkhakov <artyom.s...@gmail.com> >>> wrote: >>> >>>> 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> 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> 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. >>>>>>> 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/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-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/fd79538d-97ac-4f54-b62d-ceeb08794036%40googlegroups.com >>>> >>>> <https://groups.google.com/d/msgid/ats-lang-users/fd79538d-97ac-4f54-b62d-ceeb08794036%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-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/2367999b-fb1e-420e-b966-42c6f4aced66%40googlegroups.com >> >> <https://groups.google.com/d/msgid/ats-lang-users/2367999b-fb1e-420e-b966-42c6f4aced66%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/9ee1b434-b31e-4bca-9a24-c2a240a46172%40googlegroups.com.