A "standard" solution is to use call-by-reference:

extern
fun
runCommand
{a:vt@ype}
(c:Command(a:vt@ype), &a? >> a): void

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))

This is a bit more involved but only an implementer like you (not user)
needs to deal with it :)


On Tue, Mar 26, 2019 at 10:01 AM Artyom Shalkhakov <
artyom.shalkha...@gmail.com> 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-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/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/CAPPSPLrdSHqn-EXT_Qs%2Bb3Y6cYNag4JTQRT8uO2H-jTvDcXUwA%40mail.gmail.com.

Reply via email to