【问题标题】:How handling a list of polymorphic variants?如何处理多态变体列表?
【发布时间】:2012-03-04 17:05:10
【问题描述】:

让两种变体类型:

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

我该如何处理?

【问题讨论】:

  • “因为它们的类型不同,我需要多态变体”——不。如果您向我们提供您正在使用的真实材料,我们能够更好地为您提供帮助,但您似乎在这里为自己创造了更多的工作。

标签: list functional-programming ocaml variant polymorphism


【解决方案1】:

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

遍历 filters1 以检查我尝试过的参数的类型

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

【讨论】:

  • 实际上,我正在尝试获得一种运行时“动态”模式匹配,所以是的,我想处理多种类型,每个类型触发一个特定函数
  • 这真的没有任何意义。您无法在 OCaml 中动态匹配类型:该语言不能那样工作。您可以动态匹配类型的值,这只是普通的旧模式匹配,但类型匹配不是 OCaml 语言所允许的。你的问题还不清楚。
【解决方案2】:

我认为你的代码应该是这样的:

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)多态?

你想做什么?

【讨论】:

  • 是的,我得到了错误:` | FilterB(fB) -&gt; fB.handleB event; () Error: This expression has type typeA but an expression was expected of type typeB
【解决方案3】:

当你说

match fil with
`FilterA -> ...

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

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

如果您打算使用List.iter 执行它们,我不确定我是否看到让您的处理程序返回bool 的目的。这将返回unit,而bool 值将被丢弃。

编辑

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

【讨论】:

  • 无法编译...:This expression has type typeA but an expression was expected of type typeB
  • 我得看看你编译了什么。对于上面的片段,您不会收到此消息(我刚刚验证过)。我将代码扩展为一个完整的函数,也许这会澄清。
  • 除最后一个函数外同上:'let exec_filters filters event = List.iter (fun fil -> match fil with | FilterA { handleA = h } -&gt; h event; () | FilterB { handleB = h } -> h event; ( ) ) 过滤器;;'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多