是否有任何语言在作为参数传递的函数上实现保留的泛型?
Do any languages implement retained generics on functions passed as parameters?
运行 今天在 F# 中跨越这个:
let test<'a> (f: 'a -> unit) =
let x = f 123
let y = f "wow"
()
这会产生编译器错误,因为通用参数在每次调用 test<'a> 时必须相同,如下所述:
传递映射函数时类型推断不起作用
虽然这是有道理的,但我很好奇是否还有其他语言实现了类似的功能——也许是某种 "parameter-level generics"?
作为跟进,实施这样的事情有哪些挑战?
当然可以。在 Haskell 中,这样的东西被称为 "higher rank types":它们是允许您 "move quantification inside parentheses":
的类型
test :: (forall a. a -> ()) -> ()
test f = let x = f 123
y = f "wow"
in ()
在"challenge"中也描述了link给出的:
Rank-N type reconstruction is undecidable in general, and some
explicit type annotations are required in their presence.
不过,据我所知,只有 rank-2 类型是可判定的(参见 here)。这就是为什么在 GHC 中有两个不同的标志来启用它们。
人们也可以声称 C++ 支持这一点,因为它在参数多态性方面很奇怪但非常强大。
template<typename T>
void test(T f)
{
std::cout << f(123) << std::endl;
std::cout << f("wow") << std::endl;
}
int main()
{
test([](auto const & v)
{
// Note: This is a compile-time test
if (std::is_same_v<int, std::decay_t<decltype(v)>>)
{
return 0;
}
else
{
return 1;
}
});
}
运行 今天在 F# 中跨越这个:
let test<'a> (f: 'a -> unit) =
let x = f 123
let y = f "wow"
()
这会产生编译器错误,因为通用参数在每次调用 test<'a> 时必须相同,如下所述: 传递映射函数时类型推断不起作用
虽然这是有道理的,但我很好奇是否还有其他语言实现了类似的功能——也许是某种 "parameter-level generics"?
作为跟进,实施这样的事情有哪些挑战?
当然可以。在 Haskell 中,这样的东西被称为 "higher rank types":它们是允许您 "move quantification inside parentheses":
的类型test :: (forall a. a -> ()) -> ()
test f = let x = f 123
y = f "wow"
in ()
在"challenge"中也描述了link给出的:
Rank-N type reconstruction is undecidable in general, and some explicit type annotations are required in their presence.
不过,据我所知,只有 rank-2 类型是可判定的(参见 here)。这就是为什么在 GHC 中有两个不同的标志来启用它们。
人们也可以声称 C++ 支持这一点,因为它在参数多态性方面很奇怪但非常强大。
template<typename T>
void test(T f)
{
std::cout << f(123) << std::endl;
std::cout << f("wow") << std::endl;
}
int main()
{
test([](auto const & v)
{
// Note: This is a compile-time test
if (std::is_same_v<int, std::decay_t<decltype(v)>>)
{
return 0;
}
else
{
return 1;
}
});
}