如何处理多态变体列表?

时间:2012-03-04 17:05:11

标签: list functional-programming ocaml variant polymorphism

让两种变体类型:

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

我该如何处理?

3 个答案:

答案 0 :(得分:5)

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

  

迭代filters1以检查我尝试的参数的类型

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

答案 1 :(得分: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)变为多态?

你想做什么?

答案 2 :(得分:2)

当你说

match fil with
`FilterA -> ...

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

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

如果您要使用bool来执行它们,我不确定是否会让您的处理程序返回List.iter。这将返回unit,并且bool值将被丢弃。

修改

有一个更深层次的打字问题,Ptival解释得很好。因此,即使您修复了模式,您仍然需要重新考虑您的计划。一个可能的做法是使用变体(顺便说一下,不一定是多态变体)来跟踪事件的类型。