G'Camlメモ

コマンドラインオプション

G'Caml関係の警告は-w G, -w gで出したり出さなかったりできる様子。

拡張構文

generic

基本。

# let ( + ) = generic ( + ) | ( +.);;
Characters 4-33:
  let ( + ) = generic ( + ) | ( +.);;
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning G: Unused_var.expression: not yet implemented
val ( + ) : [| int -> int -> int | float -> float -> float |] = <generic>
# 1 + 2;;
- : int = 3
# 1.1 + 2.2;;
- : float = 3.3000000000000003

それぞれの型を明記できたりする。再帰させるときに型推論の補助として必要らしい。

# let ( + ) = generic : int -> int -> int => ( + ) 
  | : string -> string -> string => ( ^ );;
Characters 4-89:
  ....( + ) = generic : int -> int -> int => ( + )
  | : string -> string -> string => ( ^ )..
Warning G: Unused_var.expression: not yet implemented
val ( + ) : [| int -> int -> int | string -> string -> string |] = <generic>
# 1 + 2;;
- : int = 3
# "a" + "b";;
- : string = "ab"

通常は暗黙に生成される、型情報を受け取る部分を、明示的に書くこともできる様子。

# generic val x : {'a} => 'a -> int = fun ty x -> 1;;
Unused_var.structure_item
val x : { 'a } => 'a -> int = <generic>

[: t :]

型式からRtype.type_exprを得る拡張構文。
( = )で比較したりパターンマッチに使ったりできる。

# [: int :];;
- : Rtype.type_expr = [: int(*1*) :]
# [: int :];;
- : Rtype.type_expr = [: int(*1*) :]
# [: int * int :];;
- : Rtype.type_expr = [: int(*1*) * int(*1*) :]

r^を使って他の変数を参照できる。

# let x = [: int :] in [: ^x :];;
- : Rtype.type_expr = [: int(*1*) :]

typedecl t

型名からRtype.type_declarationを得る拡張構文。typedeclは予約語。
宣言の情報なので識別子になっている型じゃないとダメ。int listやstring * string等は書けない。typedecl listは書ける。

# typedecl int;;
- : Rtype.type_declaration =
{Rtype.type_name = "int"; Rtype.type_params = []; Rtype.type_arity = 0;
 Rtype.type_kind = Rtype.Type_abstract; Rtype.type_manifest = None;
 Rtype.type_variance = []; Rtype.type_defined_with = []}
# typedecl in_channel;;
- : Rtype.type_declaration =
{Rtype.type_name = "in_channel"; Rtype.type_params = [];
 Rtype.type_arity = 0; Rtype.type_kind = Rtype.Type_abstract;
 Rtype.type_manifest = None; Rtype.type_variance = [];
 Rtype.type_defined_with = []}

G'Camlの標準ライブラリ

Builtintypes

Rtypeと別だけどRtypeの中ではObj.magicして使われてたりして、内部の都合で存在するモジュールっぽい。型も<abstr>なので直接使う必要は無さげ。

module Builtintypes :
  sig
    type type_declaration
    val int : type_declaration
    val char : type_declaration
    val string : type_declaration
    val float : type_declaration
    val bool : type_declaration
    val unit : type_declaration
    val exn : type_declaration
    val array : type_declaration
    val list : type_declaration
    val format6 : type_declaration
    val option : type_declaration
    val nativeint : type_declaration
    val int32 : type_declaration
    val int64 : type_declaration
    val lazy_t : type_declaration
  end

Rtype

typedecl t[: t :]で得られる型情報の型が宣言されている。

module Rtype :
  sig
    module Ident : sig type t = string * int end
    module Path :
      sig
        type t =
            Pident of Ident.t
          | Pdot of t * string * int
          | Papply of t * t
        val name : t -> string
      end
    type mutable_flag = Immutable | Mutable
    type label = string
    type private_flag = Private | Public
    type record_representation =
        Record_regular
      | Record_float
    type type_expr = type_declaration_param raw_type_expr
    and type_desc = type_declaration_param raw_type_desc
    and type_declaration = type_declaration_param raw_type_declaration
    and type_declaration_param = Path.t * type_declaration_box
    and type_declaration_box =
        Box of type_declaration
    and type_kind = type_declaration_param raw_type_kind
    and 'a raw_type_expr =
      desc : 'a raw_type_desc;
    }
    and 'a raw_type_desc =
        Tvar
      | Tarrow of label * 'a raw_type_expr * 'a raw_type_expr
      | Ttuple of 'a raw_type_expr list
      | Tconstr of 'a * 'a raw_type_expr list
    and 'a raw_type_declaration =
      type_name : string;
      type_params : 'a raw_type_expr list;
      type_arity : int;
      type_kind : 'a raw_type_kind;
      type_manifest : 'a raw_type_expr option;
      type_variance : (bool * bool * bool) list;
      type_defined_with : 'a list;
    }
    and 'a raw_type_kind =
        Type_abstract
      | Type_variant of (string * 'a raw_type_expr list) list * private_flag
      | Type_record of (string * mutable_flag * 'a raw_type_expr) list *
          record_representation * private_flag
    val unbox : type_declaration_box -> type_declaration
    val dummy : type_declaration
    val equal : type_expr -> type_expr -> bool
    val raw_equal :
      ('a -> 'a -> bool) -> 'a raw_type_expr -> 'a raw_type_expr -> bool
    val raw_subst :
      ('a raw_type_expr * 'a raw_type_expr) list ->
      'a raw_type_expr -> 'a raw_type_expr
    val subst : (type_expr * type_expr) list -> type_expr -> type_expr
    val attached_info : 'a raw_type_expr -> 'a list
    val iter_type_expr :
      ('a raw_type_expr -> unit) -> 'a raw_type_expr -> unit
    val reset_names : unit -> unit
    val print_path : Format.formatter -> Path.t -> unit
    val raw_print :
      (Format.formatter -> 'a -> unit) ->
      Format.formatter -> 'a raw_type_expr -> unit
    val raw_print_type_declarations :
      (Format.formatter -> 'a -> unit) ->
      Format.formatter -> 'a raw_type_declaration list -> unit
    val print : Format.formatter -> type_expr -> unit
    val print_type_declarations :
      Format.formatter -> type_declaration list -> unit
    val print_related_type_declarations :
      Format.formatter -> type_declaration -> unit
    val int : type_declaration
    val char : type_declaration
    val string : type_declaration
    val float : type_declaration
    val bool : type_declaration
    val unit : type_declaration
    val exn : type_declaration
    val array : type_declaration
    val list : type_declaration
    val format6 : type_declaration
    val option : type_declaration
    val nativeint : type_declaration
    val int32 : type_declaration
    val int64 : type_declaration
    val lazy_t : type_declaration
    val builtin_types : type_declaration list
  end

gcamllib

Cplus

intとfloatのオーバーロードされた加算。intとfloatを直接足すこともできる。

module Cplus :
  sig
    val plus :
      [| int -> int -> int | float -> float -> float | int -> float -> float
       | float -> int -> float | int -> int -> float |]
  end

Garith

組み込み型の四則演算を全部( + ), ( - ), ( * ), ( / )で書けるようにする。

module Garith :
  sig
    val ( + ) :
      [| int -> int -> int | float -> float -> float
       | int32 -> int32 -> int32 | int64 -> int64 -> int64
       | nativeint -> nativeint -> nativeint |]
    val ( - ) :
      [| int -> int -> int | float -> float -> float
       | int32 -> int32 -> int32 | int64 -> int64 -> int64
       | nativeint -> nativeint -> nativeint |]
    val ( * ) :
      [| int -> int -> int | float -> float -> float
       | int32 -> int32 -> int32 | int64 -> int64 -> int64
       | nativeint -> nativeint -> nativeint |]
    val ( / ) :
      [| int -> int -> int | float -> float -> float
       | int32 -> int32 -> int32 | int64 -> int64 -> int64
       | nativeint -> nativeint -> nativeint |]
  end

Gcaml

module Gcaml :
  sig
    val typeof : { 'a } => 'a -> Rtype.type_expr
    type dyn
    exception Coercion_failure of Rtype.type_expr * Rtype.type_expr
    val dyn : { 'a } => 'a -> dyn
    val coerce : { 'a } => dyn -> 'a
    val type_of_dyn : dyn -> Rtype.type_expr
    val obj_of_dyn : dyn -> Obj.t
    val dyn_of : Rtype.type_expr -> Obj.t -> dyn
  end

typeofは値の型を取得する。多相型の関数の中で引数の型を知りたい時に使える。
dynは型無し変数として使える。coerceで値を取り出す。取り出した値は型が不定のままオーバーロードされた関数に渡すこともできる。具体的な型が指定された時点で型が合わなければCoercion_failureが発生する。

# Gcaml.typeof 1;;
- : Rtype.type_expr = [: int(*1*) :]
# let x = Gcaml.dyn 2;;
val x : Gcaml.dyn = <abstr>
# Gcaml.coerce x;;
- : { Gcaml.dyn -> 'b < { 'a } => Gcaml.dyn -> 'a } => 'b = <generic>
# (Gcaml.coerce x : int);;
- : int = 2
# let y = Plus.double (Gcaml.coerce x);;
val y :
  { 'b -> 'b < { 'a -> 'a -> 'a < [| int -> int -> int
                                   | float -> float -> float |] } =>
                 'a -> 'a,
    Gcaml.dyn -> 'b < { 'c } => Gcaml.dyn -> 'c } => 'b =
  <generic>
# (y: int);;
- : int = 4
# (y: float);;
Exception: Gcaml.Coercion_failure ([: int(*1*) :], [: float(*4*) :]).

Generic

タプルとかリストとか中まで見てくれるiterとmap。
何も説明が無く、使い方はわかるようなわからないような。

module Generic :
  sig
    val iter :
      ((Gcaml.dyn -> unit) -> Gcaml.dyn -> unit) -> Gcaml.dyn -> unit
    val map :
      ((Gcaml.dyn -> Gcaml.dyn) -> Gcaml.dyn -> Gcaml.dyn option) ->
      Gcaml.dyn -> Gcaml.dyn
  end
# Generic.iter (fun x y -> try Gprint.eprint (Gcaml.coerce y: int)
  with Gcaml.Coercion_failure _ -> ()) (Gcaml.dyn (1, 2));;
1
2
- : unit = ()
# Generic.iter (fun x y -> try Gprint.eprint (Gcaml.coerce y: int)
  with Gcaml.Coercion_failure _ -> ()) (Gcaml.dyn [(1, 2); (3, 4)]);;
1
2
3
4
- : unit = ()

Gprint

説明不要。無いと死ぬ。G'Camlの存在意義と言っていいモジュール。

module Gprint :
  sig
    type depth_info =
      max_depth : int;
      cur_depth : int;
    }
    type base_printer = depth_info -> Format.formatter -> Obj.t -> unit
    val base_printers :
      (Rtype.type_declaration * (base_printer list -> base_printer)) list
    type printer =
        Rtype.type_expr -> depth_info -> Format.formatter -> Obj.t -> unit
    val gen_print : printer -> printer
    val printer :
      Rtype.type_expr -> ?max_depth:int -> Format.formatter -> Obj.t -> unit
    val print : { 'a } => ?max_depth:int -> Format.formatter -> 'a -> unit
    val eprint : { 'a } => ?max_depth:int -> 'a -> unit
  end

Gtest

このモジュールは何がやりたいのかよくわからない。

module Gtest :
  sig
    val t_dest_ :
      Rtype.type_declaration_param Rtype.raw_type_expr -> Obj.t -> Gcaml.dyn
    val t_dest : { 'a } => 'a -> Gcaml.dyn
    val t_cnst_ : Rtype.type_expr -> 'a -> Gcaml.dyn
    val t_cnst : { 'a } => 'a -> Gcaml.dyn
  end

Plus

intとfloatのオーバーロードされた加算。

module Plus :
  sig
    val plus : [| int -> int -> int | float -> float -> float |]
    val double :
      { 'a -> 'a -> 'a < [| int -> int -> int | float -> float -> float |] }
        => 'a -> 'a
  end

Rec

intのリストを再帰的に辿って表示してくれる。

module Rec :
  sig
    val print :
      [| int -> unit
       | { 'b -> unit < 'a, 'b list -> unit < 'a } => 'b list -> unit |]
      as 'a
  end
# Rec.print [1; 2; 3];;
123- : unit = ()
# Rec.print [[1; 2]; [3; 4]];;
1234- : unit = ()

Safevio

型情報も一緒に出力するタイプのマーシャリングらしい。

module Safevio :
  sig
    type fingerprint =
        BuiltinBase of string
      | Digest of Digest.t
      | Recursive of string
    type fingerprint_type_expr = fingerprint Rtype.raw_type_expr
    type type_signature = fingerprint Rtype.raw_type_declaration list
    val type_expr : Rtype.type_expr -> fingerprint_type_expr
    val fingerprint : Rtype.type_declaration -> fingerprint
    val type_signature : Rtype.type_declaration -> type_signature
    val print_type_signature :
      Format.formatter -> Rtype.type_declaration -> unit
    val string_of_type_signature : Rtype.type_declaration -> string
    val output_value : { 'a } => out_channel -> 'a -> unit
    val input_value : { 'a } => in_channel -> 'a
  end