Is it possible to write something similar to C++'s
template <typename... T> std::string dup(int n, std::string s, T... tail) {
std::string result;
for (int i = 0; i < n; ++i) {
result += s;
}
if constexpr (sizeof...(tail) == 0) {
return result;
} else {
return result + dup(tail...);
}
}
std::cout << dup(1, std::string("abc"), 2, std::string("xyz"), 3, std::string("a")) << std::endl; // abcxyzxyzaaa
I tried to write the following function in TypedRacket
#lang typed/racket
(: repeat-string (-> Integer String String))
(define (repeat-string n str)
(apply string-append (build-list n (λ (_) str))))
(: dup (All (T ...) (-> Integer String T ... T String)))
(define (dup n s . tail)
(define result (repeat-string n s))
(cond [(empty? tail) result]
[else (string-append result (apply dup tail))])
)
but i have typecheck error:
Type Checker: Bad arguments to function in 'apply': Domain: Integer String T ... T Arguments: (List T ... T) in: (apply dup tail)
Honestly, i dont understand why arguments are (List T ... T) but not (T ... T). Moreover, the function is correct, untyped Racket produces the correct results
The key to doing this with proper type safety is to specify the type of your function using
->*with a#:rest-starkeyword:If your function takes a list directly, you can use
RecandList*to create the type signature. You can also then definedupin terms of it: