ATS1 and ATS2 are very similar modulo minor syntactic differences.
There isn't really much point in learning ATS1.
I did not implement the printf stuff in ATS2 because it was not particularly
useful.
I have to say that 'printf' was a poor idea to start with in the first place.
There are a lot more types than letters.
>> So printf "%c %f" is of type "Char -> Double -> String"
By the say, this is not true printf. The printf supported in ATS1 is a variadic function
(just like in C).
>>But I assume you mean more generally that the idea of having a variadic function and parsing the first argument to determine the number of additional arguments and their types wasn't useful.It may be useful. But using %s for string, %c for char, etc. does notlook like a good design.>>Is the variadic function capability what is missing in ATS2? If not, what is the difference that ATS1 allows it and ATS2 doesn't?Variadic functions are supported in ATS2.
To support printf, one needs to parse a constant format string. I did not implement such a parser in ATS2.
#include
"share/atspre_staload.hats"
#include
"share/atspre_staload_libats_ML.hats"
datatype tag(t@ype) =
| T1(int) | T2(@(int, string))
extern
fun{a:t@ype} foo(tag(a), a): void
implement
foo<int>(tag, data) =
(
case- tag of T1() => print_int(data)
)
implement
foo<(int,string)>(tag, data) =
(
case- tag of T2() => (print_int(data.0); print_string(data.1))
)
val () = foo(T1(), 1)
val () = foo(T2(), @(1, "A"))
implement main0() = ((*void*))
abstype string(string)
abstype format(string)
datatype
Format(type) =
|
{a:type}
Number(int -> a) of Format(a)
|
{a:type}
Str(string -> a) of Format(a)
|
{a:type}
Lit(a) of (String, Format(a))
|
End(string) of ()
extern
fun
toFormat
{cs:string}
(string(cs)): Format(format(cs))
extern
fun
printfFmt
{a:type}
(fmt: Format(a), acc: string): a
extern
fun
printf
{cs:string}(fmt: string(cs)): format(cs)
implement
printf(fmt) = printfFmt(toFormat(fmt), "")
I can only outline a way in ATS that more or less matches
the printf example in your message. In ATS, the function PrintfType
can not be defined.
On the other hand, if I understand correctly, your printf code in Idris would
not be so easy to use if the format string is not a constant. For instance,
I remember seeing an example in K&R where the format string is constructed
at run-time.
Although I'm not sure how it works under the hood, the Idris example does work with run-time constructed strings. That was originally what I was trying to figure out: whether the strict separation between statics and dynamics in ATS made this approach constant-only. But then I couldn't figure out how to translate the example.
Although I'm not sure how it works under the hood, the Idris example does work with run-time constructed strings. That was originally what I was trying to figure out: whether the strict separation between statics and dynamics in ATS made this approach constant-only. But then I couldn't figure out how to translate the example.My claim is that it is not "easy". Say I have the following calls:printf (foo(0)) 100printf (foo(1)) "100"foo(0) returns a string containing %d (but not other occurrences of %)foo(1) returns a string containing %s (but not other occurrences of %)In order for the above code to typecheck at compile time, the above propertiesabout 'foo' need to be made known to the typechecker of Idris. I am curious abouthow this can actually be done in Idris.
Since PrintfType can't be an ATS function, is there a more canonical way to do a function like this printf thing in ATS? Or is this just a current limitation of the language?
I see what you are saying though. And it does strike me as kind of mysterious. (In fact part of the reason I started playing with ATS is that I couldn't understand what Idris was doing under the hood to make my code work.) If it helps, AFAIK, foo has to be a total function. So it could just calculate foo(0) at compile time in your example.
Since PrintfType can't be an ATS function, is there a more canonical way to do a function like this printf thing in ATS? Or is this just a current limitation of the language?
Given the design of ATS, I see it as a fundamental limitation of ATS.
But useful systems all have limitations :)
If I am to support 'printf', I would only handle constant format strings. Then
I can write a parsing function parseFmt externally. Then I can write code like
val () = printf(##parseFmt("x(int) = %i and y(string) = %s"), 1, "A")