SML#のファンクタ引数の罠っぽい挙動
あまりにも書くことがないので SML#(1.2.0) でハマッた挙動を書いておきます。
バグなのか仕様なのかちょっと判断に迷います。(githubに書くのは緊張するのです(;´∀`) )
実装が以下。 structure T を受け取り、Sという別名を付けるだけのファンクタです。
(* a.sml *) functor F (T : sig type t val f : t -> int end) = struct structure S = T end
で、以下が間違った(コンパイル出来ない) .smi ファイル。
structureの宣言では リプリケーション宣言 が使えるハズなのでコンパイル出来て欲しいところです。
_require "basis.smi" (* a.smi *) functor F (T : sig type t val f : t -> int end) = struct structure S = T end (* $ smlsharp a.sml $ a.smi:3.8-16.2 Error: (name evaluation CP-720) Provide check fails (functor body signature mismatch): F $ *)
実装と全く同じやんかー(´・ω・`)
で、以下が正しい(コンパイル出来る) .smi ファイル。
_require "basis.smi" (* a.smi *) functor F (T : sig type t val f : t -> int end) = struct structure S = struct type t val f : t -> int end end
ヘッダファイルの方が実装より長いとかよく分からない事態になってますが、ちゃんとコンパイル出来ます。
ファンクタの引数はシグネチャであって実体ではないので参照することは出来ないんでしょう。多分。
ですが、上の例で受け取るシグネチャを sig type t end だけにすると、コンパイル出来ない例に出した方のコードでもコンパイル出来てしまいます。*1
ファンクタの引数をそのまま使いまわすことが必ずダメというワケでもないんですねー。
…バグなんでしょうか? もしバグじゃなくても使えるようにして欲しいですね。
おわり
残念ながら現状では SML# でファイルを跨いでファンクタを使う(=分割コンパイルする)ことは鬼門と言わざるを得ないので、SML#使ってみようという方は注意して下さい。
このほかにも恐らく無数の罠に嵌ります (言い過ぎか汗)
*1:どうも structure や signature を特別扱い*しなさすぎ*てるんじゃないかと予想