模式匹配记录的歧义

时间:2017-07-04 11:54:32

标签: ocaml

我从this question了解到可以使用模式匹配记录。但是,我注意到我在尝试匹配不同类型的记录时遇到了麻烦。

我在这个例子中的目标是能够区分不同的记录。我给出了一个记录,我不完全确定它是哪种类型,我试图用模式匹配来解决它。

这是一个简化的例子:

https://www.npmjs.com/package/viz.js

当我尝试构建此文件时,我得到:

module IceCream = struct
  type t = {
    temperature: float;
    toppings: string list;
  }
end

module Candy = struct
  type t = {
    flavour: string;
    colour: string;
    volume: int;
  }
end


(* Could be Candy or IceCream *)
let example =
  { Candy.
    flavour = "mint";
    colour = "green";
    volume = 10 }

let printFavoriteTreat treat = match treat with
  | { Candy.
      flavour = "mint";
      colour;
      volume } -> "It's Candy"
  | { IceCream.
      temperature;
      toppings } -> "It's IceCream"


let () = printFavoriteTreat example

这样做的可能吗?

3 个答案:

答案 0 :(得分:3)

皮埃尔提供的答案很棒,但这个例子并不多。 (我一直讨厌名为ab ...)

的示例

所以,正如皮埃尔建议的那样,你可以像这样定义你的类型:

type ice_cream = {
  temperature: float;
  toppings: string
}

type candy = {
  flavor: string;
  color: string;
  volume: int
}

然后,您可以将类型treat定义为这两种类型的variant

type treat =
| Candy of candy
| IceCream of ice_cream

然后,使用模式匹配:

let print_favorite_treat = function
| Candy _ -> print_endline "You love candy!"
| IceCream _ -> print_endline "You love ice cream!"

答案 1 :(得分:3)

  

我给出的记录是,我不完全确定它是哪种类型,我试图通过模式匹配来解决这个问题。

这是不可能的。类型仅在编译时存在,因此无法在运行时检查它的类型。

换句话说,在一个有效的程序中,你可以在每个表达式上放置一个类型注释(在大多数情况下,由于类型推断,你不必这样做)。如果你不能这样做那么你应该以不同的方式设计你的程序,比如使用其他人建议的和类型 - 在这种情况下,两个值将具有相同的类型(在编译时)但是具有不同的构造函数(在运行时)。 / p>

答案 2 :(得分:1)

您尝试在不使用变体类型的情况下匹配不同类型。

您正在使用的模块语法无济于事,因为模块只是构造代码。您可以定义以下类型:

type a = {
     temperature: float;
     toppings: string list;
  }

type b =  {
    flavour: string;
    colour: string;
    volume: int;
  }

但结果会是一样的。

消除歧义的方法是使用变体类型(或以下示例中未描述的联合类型):

let printFavoriteTreat treat = match treat with
  | `A{ Candy.
      flavour = "mint";
      colour;
      volume } -> "It's Candy"
  | `B { IceCream.
      temperature;
      toppings } -> "It's IceCream"
;;

并且

let () = printFavoriteTreat (`A example)