lib/Prelude.hs に追加した、even, odd は、内部であやまって Num t => t が Integer に特殊化されてしまっていて、Int の引数をあたえると abend する。
(Prelude.even :: ([Prelude.Integral t1408] :=> (t1408 -> Prelude.Bool))) =
\(Prelude.even.DARG0 :: Ä) ->
\(_Prelude.even.U1 :: ([Prelude.Integral t1402] :=> t1402)) ->
((((Prelude.== :: ([Prelude.Eq t1404] :=> (t1404 -> (t1404 -> Prelude.Bool))))
${Prelude.Integer Prelude.Eq})
((((Prelude.rem :: ([Prelude.Integral t1405] :=> (t1405 -> (t1405 -> t1405))))
(Prelude.even.DARG0 :: Å))
(_Prelude.even.U1 :: ([Prelude.Integral t1402] :=> t1402)))
(((Prelude.fromInteger :: ([Prelude.Num t1406] :=> (Prelude.Integer -> t1406)))
(Prelude.even.DARG0 :: Å))
(2 :: Prelude.Integer))))
(((Prelude.fromInteger :: ([Prelude.Num t1407] :=> (Prelude.Integer -> t1407)))
(Prelude.even.DARG0 :: Å))
(0 :: Prelude.Integer)))
gcd, lcm でも同じ問題が発現。gcdlcm2.hs
概要にあげた core では、Prelude.Eq t1404 にあたる型変数が Prelude.Integral t1408 に一致せず、lookupDict が Nothing を返していた。(その結果 defaulting が実施され Integer に)
原因は、Eq が Integral に一致せず、Integral の supers のどれにも一致しなかったため。 Eq は Integral の super の super なので、再帰的に検査しなければならなかった。
@@ -197,10 +197,10 @@ lookupDictArg (c, y) = do
ce <- getCe
let d = zip (map (\((IsIn i t), _) -> (i, apply s t)) pss) [(0::Int)..]
lookupDict (k, tv) (((c, tv'), i):d')
- | tv == tv' && (k == c || k `elem` super ce c) = Just i
+ | tv == tv' && c `isin` k = Just i
| otherwise = lookupDict (k, tv) d'
lookupDict _ [] = Nothing
-
+ c1 `isin` c2 = (c1 == c2)|| (or $ map (`isin` c2) (super ce c1))
ret = case lookupDict (c, TVar y) d of
Nothing -> Nothing
Just j -> let (_, n) = pss !! j
また、CodeGen も同様に、super の super も処理する必要があった。
--- a/compiler/src/CodeGen.hs
+++ b/compiler/src/CodeGen.hs
@@ -8,7 +8,7 @@ import Symbol
import Typing (ClassEnv (..), super)
import Control.Monad.State.Strict
-import Data.List (find, intercalate)
+import Data.List (find, intercalate, nub)
import Data.List.Split (splitOn)
import qualified Data.Map as Map
import Data.Maybe (fromJust, fromMaybe)
@@ -486,7 +486,8 @@ emitInsts dest dicts ((qin, qcn):ctab) ce = do
let ms = ddMethods $ fromJust $ find ((== qcn). ddId) dicts
msM = map mangle ms
pdname = cls2dictNameM qcn
- supers = super ce qcn
+ f c = c : concatMap f (super ce c)
+ supers = nub $ concatMap f (super ce qcn)
sdname = map cls2dictNameM supers
dname = cls2dictNameM $ qin ++ "@" ++ qcn
mname = modname qin
これによって、oddInt.hs は通るようになった ⇒ sample220.hs
だが、gcdlcm2.hs はまだダメ。こちらも、lookupDict が Nothing を返しているのだが、 クラスではなく tv が不一致であるらしく、原因は別のところにあるようだ。
092 対処により、gcdlcm2.hs も通るようになった。