多相バリアントと木構造
多相バリアントでも、木構造のデータ型を定義してしまうと拡張が大変だよね、というお話。
ツリー構造じゃない場合
適当にデータ型を定義するよ!
type value = [ `Var of string | `String of string ]
多相バリアントだから簡単に拡張できるね、やった!
type value2 = [value | `Int of bool]
ツリー構造
じゃあ、次は木構造を定義してみる。
type expr = [ `Var of string | `String of string | `Lambda of string * expr]
拡張してみる。
type expr2 = [ expr | `Int of int ]
じゃあ、さっそく使ってみよう。
# (`Lambda ("x",`Int 42) : expr2);; Characters 1-22: (`Lambda ("x",`Int 42) : expr2);; ^^^^^^^^^^^^^^^^^^^^^ This expression has type [> `Lambda of string * ([> `Int of int ] as 'a) ] but is here used with type expr2 = [ `Int of int | `Lambda of string * expr | `String of string | `Var of string ] Type 'a is not compatible with type expr = [ `Lambda of string * expr | `String of string | `Var of string ] The second variant type does not allow tag(s) `Int
`Lambdaのパラメータはexpr2じゃなくてexprだから、ちゃんと拡張できてないよ ><。
いちおう解決策
再帰的になっている部分を型変数に逃がしてやれば、いちおう回避できるよ! ホントにこれでいいのかは、はなはだ疑問だけど。(これでいいらしいです。コメント欄参照)
type 'a expr_type = [ `Var of string | `String of string | `Lambda of string * 'a] type expr = expr expr_type type 'a expr_type2 = ['a expr_type | `Int of int] type expr2 = expr2 expr_type2
(`Lambda ("x",`Int 42) : expr2);; - : expr2 = `Lambda ("x", `Int 42)