077: Num を Eq, Show 2つのサブクラスにする

↑up

概要

現状では、2つ以上のスーパークラスに対応していないため、 Num は Eq のサブクラスとなっており、Show のサブクラスになっていない。

なので、以下のようなプログラムにおいて、f, g の型は以下のようになってしまっている:

f x y = let z = x * y
            c = x == y
        in (z, c)

g x y = print (x * y)

main = do print $ f 1 2
          print $ f (1::Double) 1
          g 3 3
          g (3::Double) 10

f は正しく (Num a) => a -> a -> (a, Bool) だが、 g の方が (Num a, Show a) => a -> a -> IO () となってしまっている。

これは、Num が Show のサブクラスでもあるなら、(Num a) => a -> a -> IO () となる。

調査ログ

2020-05-16 (Sat)

ソースの読み取り以降の部分は、複数のスーパクラスに対応するように作ってあったので、 微修正だけでOKだった。

index 938764d..961e04c 100644
--- a/compiler/lib/Prelude.hs
+++ b/compiler/lib/Prelude.hs
@@ -192,7 +192,7 @@ instance Show Char where
 -- todo: should convert to printable characters
 showLitChar c = (++) [c]
 
-class (Eq a) => Num a where
+class (Eq a, Show a) => Num a where
   (+), (-), (*) :: a -> a -> a
   negate        :: a -> a
   signum        :: a -> a
diff --git a/compiler/src/Rename.hs b/compiler/src/Rename.hs
index 8e78cfb..d45e99e 100644
--- a/compiler/src/Rename.hs
+++ b/compiler/src/Rename.hs
@@ -245,6 +245,8 @@ renClassDecls dcls = do
   where
     extr_sc Nothing                                  = []
     extr_sc (Just (A.ParTy (A.AppTy (A.Tycon i) _))) = [origName i]
+    extr_sc (Just (A.TupleTy ts))                    =
+      map (\(A.AppTy (A.Tycon i) _) -> origName i) ts
     extr_sc (Just t) = error $ "extr_sc: " ++ show t
 
     clsadd (maybe_sc, A.AppTy (A.Tycon n) _) = do

修正後の f, g の型: