# 076: showlist2.hs が再びエラー、dictionary not found [↑up](bunny_notes) - issued: 2020-05-15 - 分類: A サンプルコードが fail - status: Closed (2020-10-01) ## 概要 [035](bissue035) 対処により、以前通っていた showlist2.hs がエラーするようになって しまったので、sample194 から再度降格。 現象: $$
{
$ ./trun testcases/showlist2.hs
# 1. tcompile
source file: testcases/showlist2.hs
dst dir: /showlist2
doCompile ... done.
implicitPrelude ... done.
doCompile ... bunnyc: Error: dictionary not found: ("Prelude.Show",Tyvar "t40" Star,[(IsIn "Prelude.Show" (TVar (Tyvar "t44" Star)),"Main.l1.l0.l0.l0.showlist'.DARG0"),(IsIn "Prelude.Show" (TVar (Tyvar "t47" Star)),"Main.l1.l0.showList.DARG0")])
CallStack (from HasCallStack):
error, called at src/DictPass.hs:261:25 in main:DictPass
$$}
## 調査ログ
## 2020-09-30
### 現象の絞り込み
問題を特定するために、showlist2.hs を小さくしていく。
以下のようにすると、エラーせずに実行できてしまった:
$${
main = do
putStrLn $ showlist' [1]
where
showlist' [] = "[]"
showlist' [x] = "[" ++ show x ++ "]"
$$}
以下では再現:
$${
main = do
putStrLn $ showlist' [1]
where
showlist' [x] = "[" ++ show x ++ "]"
showlist' (x:xs) = "[" ++ foldl (\s t -> s ++ "," ++ show t) (show x) xs ++ "]"
$$}
もうすこし簡単にしてみた(showlist2b.hs):
$${
showlist' [x] = show x
showlist' (x:xs) = showlist' xs
main = putStrLn $ showlist' [1]
$$}
これをコンパイルすると、次のようになる。
$${
$ ./trun testcases/showlist2b.hs
# 1. tcompile
source file: testcases/showlist2b.hs
dst dir: /showlist2b
doCompile ... done.
implicitPrelude ... done.
doCompile ... bunnyc: Error: dictionary not found: ("Prelude.Show",Tyvar "t20" Star,[(IsIn "Prelude.Show" (TVar (Tyvar "t22" Star)),"Main.showlist'.DARG0")])
CallStack (from HasCallStack):
error, called at src/DictPass.hs:261:25 in main:DictPass
$$}
${--ddump-core0} の結果は次のとおり (showlist' 部のみ):
$${
(Main.showlist' :: ([Prelude.Show t22] :=> ([t22] -> [Prelude.Char]))) =
\(_Main.showlist'.U1 :: ([Prelude.Show t7] :=> [t7])) ->
case (_Main.showlist'.U1 :: ([Prelude.Show t7] :=> [t7])) (_Main.showlist'.U1b :: ([Prelude.Show t7] :=> [t7])) of
Prelude.: (_Main.showlist'.U2 :: t10) (_Main.showlist'.U3 :: [t10]) :: (t10 -> ([t10] -> [t10])) ->
case (_Main.showlist'.U3 :: [t10]) (_Main.showlist'.U3b :: [t10]) of
Prelude.: (_Main.showlist'.U3 :: t18) (_Main.showlist'.U4 :: [t18]) :: (t18 -> ([t18] -> [t18])) ->
((Main.showlist' :: ([Prelude.Show t20] :=> ([t20] -> [Prelude.Char])))
(_Main.showlist'.U3 :: t18))
Prelude.[] :: [t12] ->
((Prelude.show :: ([Prelude.Show t16] :=> (t16 -> [Prelude.Char])))
(_Main.showlist'.U2 :: t10))
Prelude.[] :: [t8] ->
(Prim.FAIL :: t9)
$$}
${showlist' xs} に相当する部分が
${((Main.showlist' :: ([Prelude.Show t20] :=> ([t20] -> [Prelude.Char]))) (_Main.showlist'.U3 :: t18))} なのだが、型引数が ${[t20]} なのに対して、
引数の型が ${t18} となっている(前者が型変数のリストだが、後者はリストでない)。
いっぽう、これによくにたプログラム(showlist2c.hs) ではエラーは発生しない。この core0 は以下のとおり:
$${
(Main.showlist' :: ([Prelude.Show t17] :=> ([t17] -> [Prelude.Char]))) =
\(_Main.showlist'.U1 :: ([Prelude.Show t7] :=> [t7])) ->
case (_Main.showlist'.U1 :: ([Prelude.Show t7] :=> [t7])) (_Main.showlist'.U1b :: ([Prelude.Show t7] :=> [t7])) of
Prelude.: (_Main.showlist'.U2 :: t10) (_Main.showlist'.U3 :: [t10]) :: (t10 -> ([t10] -> [t10])) ->
(((Prelude.++ :: ([t12] -> ([t12] -> [t12])))
((Prelude.show :: ([Prelude.Show t13] :=> (t13 -> [Prelude.Char])))
(_Main.showlist'.U2 :: t10)))
((Main.showlist' :: ([Prelude.Show t15] :=> ([t15] -> [Prelude.Char])))
(_Main.showlist'.U3 :: [t10])))
Prelude.[] :: [t8] -> ""
$$}
同じ部分に着目すると、
${((Main.showlist' :: ([Prelude.Show t15] :=> ([t15] -> [Prelude.Char]))) (_Main.showlist'.U3 :: [t10])))}
のようになっていて、${[t15]} と ${[t10]} が対応している。
このあたりに着目してみるとよさそう。
### 原因調査
よくみてみると、型付けうんぬんのまえに、局所変数の解決がおかしい。
${(x:xs) -> showlist' xs} が、${: U3 U4 -> showlist' U3} になっている。
どこで狂った?
ああ、ちがうな。showlist2b.hs は次のような「平坦なcase式」に展開されるはずなのだが、
$${
showlist' xs = case xs of
(y:ys) -> case ys of
(z:zs) -> showlist' ys
[] -> show y
main = do putStrLn $ showlist' [1]
putStrLn $ showlist' [1, 2, 3]
$$}
上記における ys と、z がいずれも U3 になってしまっている。
パターンマッチングコンパイラ(Pattern.ns) が入れ子になっているときのα変換でしくっている(重複しておなじ文字番号をわりあててしまっている)ようだ。
## 2020-10-01
Pattern.hs において、Case 式が深くなるときに prefix にレベル相当を足してやればよかった。
簡単に以下のように修正:
$${
--- a/compiler/src/Pattern.hs
+++ b/compiler/src/Pattern.hs
@@ -93,7 +93,7 @@ reduceMatch ci n0 k0 vs0 qs0 def0 =
matchClause c k (_:us) qs def =
Clause c us' (match
- n
+ (n ++ "._c")
(k + k)
(us' ++ us)
[(ps' ++ ps, e) | (PCon _ ps':ps, e) <- qs]
$$}
showlist2.hs は sample282.hs としてクローズ。