2012-03-04 60 views
3

让两人变量类型:如何处理多态变体列表?

type typeA = 
    | A1 
    | A2 
;; 

type typeB = 
    | B1 of typeA 
    | B2 of typeA 
;; 

和类型检查功能:

let isA1 = function A1 -> true | _ -> false;; 
let isA2 = function A2 -> true | _ -> false;; 
let isB1 = function B1 e -> true | _ -> false;; 
let isB2 = function B2 e -> true | _ -> false;; 

我想创建的那些功能的列表来检查A型或B

的元素因为它们是不同类型的,所以我需要多态变体,并且我得到:

type filterA = 
{ 
    handleA : typeA -> bool; 
};; 

type filterB = 
{ 
    handleB : typeB -> bool; 
};; 

type filterslist = [`FilterA of filterA | `FilterB of filterB] list ;; 

let filters1 = [`FilterA { handleA = isA1 }; `FilterB { handleB = isB1 }] ;; 

所以现在我要遍历filters1检查参数 我试过的类型:

let exec_filters filters event = List.iter (fun fil -> match fil with `FilterA -> fil.handleA event;()| `FilterB -> fil.handleB event;()) filters;; 

,但它不是赞赏:

Error: This expression has type [< `FilterA | `FilterB ] 
     but an expression was expected of type filterA 

我该如何处理呢?

+5

“因为它们是不同类型的,我需要多态变体” - 不。如果你给我们提供与你合作的真实东西,我们可以更好地帮助你,但看起来你正在为自己创造更多的工作。 – Ashe 2012-03-05 01:43:19

回答

5

您正在使用类似于Scheme或instanceOf的“类型检查谓词”这一事实表明您的代码可能存在某些错误。 OCaml是一种静态类型的语言,你不应该:

iterate over filters1 to check the type of the argument I tried

你为什么这样做?如果你想要处理多种类型,那么做的方式就是使用多态。多态变体可能对此有所帮助,但我仍然不相信您的代码不是以一种奇怪的方式编写的。

+0

实际上,我试图获得一种运行时的“动态”模式匹配,所以是的我想处理多种类型,每一个触发的特定功能 – codablank1 2012-03-04 22:33:54

+1

这没有任何意义。你无法在OCaml中动态匹配类型:语言不能像那样工作。您可以动态匹配类型的值,这只是普通的旧模式匹配,但匹配类型不是OCaml语言允许的。你的问题仍然不是很清楚。 – 2012-03-04 22:44:08

2

当你说

match fil with 
`FilterA -> ... 

你似乎希望这将改变fil类型,但这不是它的工作原理。模式内出现filterA类型的表达式。你想要更多的东西是这样的:

match fil with 
`FilterA { handleA = h } -> h event 

我不知道我看到有你的处理程序返回bool如果你打算使用List.iter执行它们的目的。这将返回unit,并且bool值将被丢弃。

编辑

有更深的打字问题,通过Ptival很好地解释。所以即使你修正了你的模式,你仍然需要重新考虑你的计划。一种可能的做法是使用变体(顺便说一下不一定是多态变体)来跟踪事件的类型。

+0

不能编译...:'这个表达式有类型typeA,但是表达式需要类型typeB' – codablank1 2012-03-04 22:30:24

+0

我得看看你编译的东西。你不会得到这个消息的上面的片段(我刚刚验证)。我将把代码扩展到一个完整的功能,也许这将澄清。 – 2012-03-04 22:35:52

+0

与上述相同,除了最后一个函数:“让exec_filters滤波器事件= List.iter (乐趣FIL - > 匹配FIL与 |'FilterA {handleA = H} - >ħ事件;() |'FilterB {handleB = h} - > h event;() ) filters ;;' – codablank1 2012-03-04 23:44:55

4

我觉得你的代码应该象:

let exec_filters filters event = 
    List.iter 
    (fun fil -> match fil with 
     | `FilterA fA -> fA.handleA event;() 
     | `FilterB fB -> fB.handleB event;()) 
    filters;; 

编辑:但是,这不会进行类型检查,因为event不能有类型typeAtypeB ...

为什么不把你的初始变体(typeAtypeB)多态?

你想做什么?

+0

是的我得到的错误:'| 'FilterB(fB) - > fB.handleB事件; () 错误:这个表达式的类型为typeA,但预期的表达式为typeB' – codablank1 2012-03-04 22:28:37