# 047: showpair0.hs がランタイムに IntegerShowFunc: must not occur [↑up](bunny_notes) - issued: 2020-04-25 - 分類: A サンプルコードが fail - status: Closed (2020-04-25) ## 概要 list や pair, triple などの Show クラス処理に取り掛かるまえに、 複数の辞書をうけとる関数のコンパイル状況をためそうとして、不具合に遭遇。 showpair0.hs: $$
{
f (a, b) = "(" ++ show a ++ "," ++ show b ++ ")"
main = putStrLn $ f (1, 'a')
$$}
これの core があやしい:
$${
(Main.main :: (Prelude.IO ())) =
((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) $
((((Main.f :: ([Prelude.Show t2,Prelude.Show t3] :=> ((((,) t3) t2) -> [Prelude.Char])))
${Prelude.Integer Prelude.Show})
${Prelude.Char Prelude.Show})
(((Prelude.(,) :: (t4 -> (t5 -> (((,) t4) t5))))
(1 :: ([Prelude.Num t6] :=> t6)))
'a')))
(Main.f :: ([Prelude.Show t21,Prelude.Show t22] :=> ((((,) t22) t21) -> [Prelude.Char]))) =
\(Main.f.DARG0 :: Ä) (Main.f.DARG1 :: Ä) ->
\(_Main.f.U1 :: ([Prelude.Show t7,Prelude.Show t8] :=> (((,) t8) t7))) ->
case (_Main.f.U1 :: ([Prelude.Show t7,Prelude.Show t8] :=> (((,) t8) t7))) (_Main.f.U1b :: ([Prelude.Show t7,Prelude.Show t8] :=> (((,) t8) t7))) of
Prelude.(,) (_Main.f.U2 :: t9) (_Main.f.U3 :: t10) :: (t9 -> (t10 -> (((,) t9) t10))) ->
(((Prelude.++ :: ([t11] -> ([t11] -> [t11])))
"(")
(((Prelude.++ :: ([t12] -> ([t12] -> [t12])))
(((Prelude.show :: ([Prelude.Show t13] :=> (t13 -> [Prelude.Char])))
(Main.f.DARG0 :: Å))
(_Main.f.U2 :: t9)))
(((Prelude.++ :: ([t16] -> ([t16] -> [t16])))
",")
(((Prelude.++ :: ([t17] -> ([t17] -> [t17])))
(((Prelude.show :: ([Prelude.Show t18] :=> (t18 -> [Prelude.Char])))
(Main.f.DARG0 :: Å))
(_Main.f.U3 :: t10))) ")"))))
$$}
- Main.f において、Main.f.DARG0 が二か所で用いられている(片方は DARG1 であるべき)
- Main.f の型:([Prelude.Show a,Prelude.Show b] :=> ((((,) b) a) -> [Prelude.Char]) : a, b 逆になってない?
### Main.f.DARG0 の検索部
$${
lookupDict (k, tv) (((c, tv'), i):d')
- | k == c || k `elem` super ce c = Just i
- | otherwise = Nothing
- lookupDict _ _ = Nothing
+ | tv == tv' && (k == c || k `elem` super ce c) = Just i
+ | otherwise = lookupDict (k, tv) d'
+ lookupDict _ [] = Nothing
$$}
いままで、同じクラスの述語に対応していなかったので、k ==c (たとえば "Prelude.Show" == "Prelude.Show" のみ成立で対応付けていても偶々OKだった。
これを、ただしく型変数の一致、かつ、クラス名が一致またはスーパークラスに一致すればOKと変えた。
いままでは、型変数 y は用いられていなかったわけで、正しく用いるようにしたおかげで、
let (TVar y) = case apply s (TVar x) of ... のパターンが [a] に未対処だったのが露見。
ひとまず、lib/Prelude から Show [a] に関する部分をコメントアウトした。
$${
bunnyc: Irrefutable pattern failed (TAp (TCon (Tycon "Prelude.[]" (Kfun Star Star))) (TVar (Tyvar "t215" Star))
$$}
これでも、まだ showpair0.hs はエラーする。今度は、二つの辞書を Main.f に渡す呼び出し側における順序があやしい。
つぎに呼び出し側の不具合調査と修正が必要だが、いったん master branch にマージする(make check は通っている状態)。
### 呼び出し側で逆順だった件
findApplyDict の内部関数 mkdicts は、結果を逆順に返していたので、それを利用するときに逆順にすべきだった。当初 ${foldl App e dicts} だったのを
${foldl App e (reverse dicts)} でもよかったのだが、foldr を使う形に修正:
$${
--- a/compiler/src/DictPass.hs
+++ b/compiler/src/DictPass.hs
@@ -235,8 +235,8 @@ tcExpr e@(Var (TermVar n (qv :=> t'))) qt -- why ignore qs?
++ n ++ ", " ++ show (x,n2,y,itvars))
Just v' -> mkdicts qs (Var v' : ds)
mkdicts _ _ = error "mkdicts: must not occur"
- dicts <- mkdicts qv []
- return (foldl App e dicts)
+ dicts <- mkdicts qv [] -- mkdicts returns dictionaries in reverse order
+ return (foldr (flip App) e dicts)
{-
where
appliedQv :: [Expr] -> TC (Maybe (Qual Type))
$$}
showpair0.hsは sample161 とする。
クローズ。