2017-07-04 6 views
0

this questionから、パターンマッチングをレコードと併用することができたことを知りました。しかし、さまざまな種類のレコードに一致させるのに問題があることに気付きました。パターンマッチングレコードのあいまいさ

この例で私の目標は、異なるレコードを区別することです。私はそれがどのタイプなのかが完全にはわからないという記録を与えられています。パターンマッチングを使ってそれを理解しようとしています。

ここでは簡単な例です:

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 

私は、このファイルを構築しようとした際、私が取得:

Error: The field IceCream.temperature belongs to the record type IceCream.t 
     but a field was expected belonging to the record type Candy.t 

は、この可能性のようなものをしているのですか?

+0

合計型(バリアント型、代数データ型、識別された共用体とも呼ばれます)に埋め込まれていない限り、異なる型のパターンマッチングはできません。 – didierc

答えて

3

私はそれがどのタイプであるか完全にはわかっていないという記録を与えられました。パターンマッチングを使ってそれを理解しようとしています。

これはできません。型はコンパイル時にのみ存在するため、実行時にどの型をチェックすることはできません。

つまり、有効なプログラムでは、すべての式に型注釈を付けることができます(ほとんどの場合、型推論のおかげでそうする必要はありません)。それ以外の場合は、両方の値が同じタイプ(コンパイル時)であるが、別のコンストラクタ(実行時)を持つように、プログラムを別の方法で設計する必要があります。

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) 
+0

おそらく、\ 'Bの代わりに\' Aと\ 'IceCreamの代わりに\ 'Candyを使うべきでしょう。なぜ、多型変種(なぜなら '| _ - >"私はそれを扱うのを知らない "+"を含む)を通常のものの代わりに説明する。 –

3

ピエールによって提供される回答が大きいです、しかしあまり例ではありません。その後

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

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

、あなたがしたようなタイプtreatを定義することができます:ピエールが示唆するように、あなたはこのようなあなたのタイプを定義することができ、

ので(私はいつも... abという名前の例を嫌ってきました)

let print_favorite_treat = function 
| Candy _ -> print_endline "You love candy!" 
| IceCream _ -> print_endline "You love ice cream!" 
:パターンマッチングを用いて次に

type treat = 
| Candy of candy 
| IceCream of ice_cream 

、これらの二つのタイプの

+0

great、これは共用体型を使用しています;) –

+0

関数が 'print_favorite_treat'と呼ばれていることは、ある種の' treat'型が必要であるという大きなヒントです。 :) – RichouHunter

+0

ああ、私は変種を避けることができたと思っていたが、私が試していた方法でレコードにマッチすることができないように見えます。回答:ありがとうございました。 –

関連する問題