在 Rust 中,函数没有类型,而是有一个
Fn
特征,看起来像这样:
trait Fn<A: Tuple, R> {
fn call(self, args: A) -> R;
}
那么函数的类型可以是
dyn Fn(A) -> R
。这有助于编译器优化,同时仍然非常容易理解。
在函数式语言中,我们可以类似地定义一个
Fn
类型类:
class Fn s a b where
call : s -> a -> b
但是,因为类型类中没有
Self
的概念,所以没有 dyn Fn
类型,这意味着你必须对所有内容使用泛型:
// in rust 😊
fn run_with_2(f: &dyn Fn(i32) -> i32) -> i32 {
f.call(2)
}
struct SomeFnWrapper<A,B>(Box<dyn Fn(A) -> B>);
-- in haskel 🤮
runWith2 : Callable f Int Int => f -> Int
runWith2 f = call f 2
-- creating `SomeFnWrapper` is impossible in haskell
这个问题有解决办法吗?也许我不知道有一些巧妙的使用
forall
?
我个人不喜欢的存在类型的解决方案。
class Callable s a b where
call :: s -> a -> b
data SomeCallable a b where
SomeCallable :: forall s . Callable s a b => s -> SomeCallable s a b