ocaml-blockly icon indicating copy to clipboard operation
ocaml-blockly copied to clipboard

Crash when generating and dragging variable block

Open harukamm opened this issue 6 years ago • 2 comments

ifに引数のkakakuをドラッグした際、離れなくなった。

スクリーンショット 2019-03-16 16 44 41

(maimai8さんより)

harukamm avatar Mar 18 '19 08:03 harukamm

状況は、

let f x = ? ;;
let test = f 0 = "a"

のように、テストで f の引数の型と返り値の型が異なると指定されている時に、x を ? のところに入れると型エラーとなるべきところを type_expr.js の 1180 行目で t1.label != t2.label となり例外があがっているようです。t1.label がなんなのか理解していないので原因はわかりませんが、この情報でどうにかならないでしょうか。

あと、関連して、上のプログラムでは x の型や f の返り値の型が test によって制限されていると思いますが、変化していない(コネクタの形が変化しない)ように見えます。そういう仕様でしたっけ。

kenichi-asai avatar Mar 27 '19 00:03 kenichi-asai

ご報告ありがとうございます。 うわ〜これはひどいですね(><)

あと、関連して、上のプログラムでは x の型や f の返り値の型が test によって制限されていると思いますが、変化していない(コネクタの形が変化しない)ように見えます。そういう仕様でしたっけ。

これは、let多相を入れているためかと思います。

type_expr.js の 1180 行目で t1.label != t2.label となり例外があがっているようです。

これは、 let test = f 0 = "a" に対する型推論実行時に int とstring を表す型表現を unify しようとした結果起きた型エラーです。

ちなみに label とは、代数的データ型を再現するためにつけている値です。intの型表現ならば、int用の値が、stringの型表現ならばまた異なる値が label の中に入っています。 異なる label を持つということは、つまり型が違うということなので、型変数とかでもない限り、 unify できないです。というわけで起きた例外です。 (ただ、maimai8さんが送ってくれたスクリーンショットの画像には、その例外がコンソールに現れていないのが謎ですが。。)

本来なら、そもそも xlet f x = ? 上の ? に接続できないようにするべきなのですが、「2つのコネクタは接続可能か」調べるときの型チェックがまだ不完全なのです。 実は、let多相を入れているのにも関わらず、現状だと、「2つのコネクタは接続可能か」というチェックには、単に2つの型表現が unify 可能かということしか見ていないのです。本来ならば、全体の型推論をやり直さなくてはいけないのですが。

この問題を解決するために行うべきと思っていることをメモ程度にまとめます。

  1. 2つのコネクタが接続可能かチェックするときに型推論を行い、型エラーが起きたら接続を拒絶する。
  2. 現在の型推論は「ブロックのコネクタにくっ付いている型を使う」ことで行っているが、「毎回フレッシュな型を生成して使う」こともできるように型推論を拡張する。チェック時にブロック上の型に副作用が起きないようにするため。

1.だけなら単に接続を仮定して、今まで通りの型推論を実行するのみでいいのですが、それだとlet多相を入れているために関数適用の部分の色がコロコロ変わってしまうです。毎回genしているためです。

なので、2.もできるようにしてからだなあと思いながら放置していたところです。 2.に関しては、「フレッシュな型を生成して使う」ためのフラグだけは既に用意しているのですが、まだフラグだけで機能の実装ができていないです。

harukamm avatar Mar 27 '19 08:03 harukamm