2012-07-28 80 views
4

我有很多不同的类型有共同的目的,但没有其他共同点。为了便于说明,他们很可能会成为沿着线:F#类型系统可以这样做吗?

type blah<'a> = Blah of 'a 

type huha<'a> = Huha of 'a 

我经常需要重复样板的一大块,可以去一个函数内部的线沿线的:

let f (x:something<int>) (g:something<char> -> float) : float = 

但是,这需要以某种方式强制这两种类型的东西是相同的。换句话说,我希望能够调用的函数f:显然

f (Blah 1) (fun (b:blah<float>) -> ....) 
f (Huha 1) (fun (b:huha<float>) -> ....) 

,一个简单的解决方案是创建所有类型的函数f也可能采取的歧视工会,并让每克(即f的第二个参数)检查它得到任何类型的预期。但是这意味着拥有一个庞大的类型,在每次任何事情发生变化时都会导致Universe重新编译,而且它不像在运行时检查类型也有帮助。

那么,有人可以看到一种做我想要的类型安全方式吗?非常感谢。

+0

由于这是.NET,你可以使用一个界面 - 但我不知道他们是F#中多么普遍。 – phg 2012-07-28 10:17:20

+0

接口在F#中实现,但我不确定这将如何帮助。所以我让我所有的各种类型实现一些特定的接口。现在我只想写一次代码的副本需要进入每种类型。而当我想调用该代码时,我需要动态调度来获取正确的实例。但是实现必须具有相同的类型,因此我还需要使所有参数以一些常见方式运行。这似乎具有使用歧视工会的所有弊端,并且也会更加复杂?我错过任何明显的事情吗? – user1559410 2012-07-28 10:50:11

回答

2

据我所知,你不能直接在F#中执行此操作。

但也许运营商超载将有所帮助。不过,您必须为每种类型实施f。但也许你可以委托一个通用的实现。

运算符重载的代码示例,确保正确的类型:

type T<'a> = 
    | T of 'a 
    static member (.+.) (l:T<int>, r:T<char> -> float) = 42.0 

type U<'a> = 
    | U of 'a 
    static member (.+.) (l:U<int>, r:U<char> -> float) = 13.1 


let ft (t:T<char>) = 42.0 

let fu (t:U<char>) = 42.0 

let t = T 42 .+. ft 
let u = U 13 .+. fu 

// does not compile: 
let wrong = T 42 .+. fu 
+0

非常感谢您的答复 – user1559410 2012-07-30 10:01:01