044: intlit.hs で types do not unify: (TCon (Tycon "Prelude.Int" Star),TCon (Tycon "Prelude.Integer" Star))

↑up

概要

types do not unify: (TCon (Tycon "Prelude.Int" Star),TCon (Tycon "Prelude.Integer" Star)) となるような小さなケースを作って調査する。

$ ./test-compile.sh testcases/intlit.hs
source file: testcases/intlit.hs
dst dir: /intlit
doCompile ... done.
implicitPrelude ... done.
doCompile ... bunnyc: types do not unify: (TCon (Tycon "Prelude.Int" Star),TCon (Tycon "Prelude.Integer" Star))

調査ログ

2020-04-22 (Wed)

intlit.hs :

f :: Int -> IO ()
f x = print x

main = f 10

Core0:

---- ddumpCore ----
(Main.main :: (Prelude.IO ())) =
    ((Main.f :: (Prelude.Int -> (Prelude.IO ()))) 
      (10 :: Prelude.Integer))

(Main.f :: (Prelude.Int -> (Prelude.IO ()))) =
    \(_Main.f.U1 :: Prelude.Int) ->
        ((Prelude.print :: ([Prelude.Show t0] :=> (t0 -> (Prelude.IO ())))) 
          (_Main.f.U1 :: Prelude.Int))


bunnyc: types do not unify: (TCon (Tycon "Prelude.Int" Star),TCon (Tycon "Prelude.Integer" Star))

整数リテラルの 10 が (10 :: Prelude.Integer) なのがおかしい。 だれだ、こんなことをしたのは。

trCore にあった:

trExpr2 (Ty.Lit (Ty.LitInt n)) = return e
  where
    e = Lit $ LitInt n tInteger

Typing.tiLit がやっているように、Num a => a にしなければいけない:

tiLit (LitInt _)  = do v <- newTVar Star
                       return ([IsIn "Prelude.Num" v], v)

まず、Core 言語の仕様として、Literal に Type しかついていなかったので、 これを Qual Type に変える。まずそれだけ変更して、make check パスすることを確認。

つぎに、整数リテラルにつける型を変える。

trExpr2 (Ty.Lit (Ty.LitInt n)) = do
  v <- newTVar' Star
  return (Lit (LitInt n ([IsIn "Prelude.Num" v] :=> v)))

そうすると、intlit.hs は通るようになったが、make check で 15/64 tests failed になった。

ただ、これは、DictPass の段階で defaulting しないといけないのだと思う。 (ので、おそらくこれは、劣化ではなく、未実装機能の露見)

かなりその場しのぎの実装だが、DictPass における defaulting を実装して、 make check が通るようにした。この実装をまともにするのは、別の issue 045 とする。

以下の testcase が通るようになった:

本件と 001, 002, 022 はクローズ