クラスの継承について未実装だったときの仮実装として、Prim.show の型が (a -> [Prelude.Char]) になっているため、Show のサブクラスでないものまで show できてしまう。
まず、いちばん単純な Bool から。
Prim.show が a -> [Char] なこと自体は、それでよかった。 ソース中に show があると、問答無用で Prim.show にリネームされていたのがよくなかった。
そこで、lib/Prelude.hs に以下を追加、それにあうよう Predefined を変更。
class Show a where show :: a -> [Char] data Bool = False | True instance Show Bool where show = Prim.show
Bool や Ordering など kind が * なものはうまくいったが、Show [a] や Show (,), Eq [a] など難航。
make check では 6 つ fail している状況:
kind が * -> * (またはそれ以上)のケースに対応する必要がある。少なくとも、以下の考慮が必要。
138 と139 は、deriving Show に未対応であるのが原因と思われる。
なお、deriving Show なコンテナに、show できないオブジェクトを「いれて」も、 その時点ではエラーしない。show しようとすると(実行時ではなく静的にだが)、エラー。
たとえば、↓のコードはエラーしないが、print c しようとするとコンパイルエラーになる。
f x = x * x a = [f] data B a = B a deriving Show b = B f data C a = C a c = C f instance (Show a) => Show (C a) where show (C a) = "C " ++ show a main = do print $ (head a) 5 let B g = b print $ g 4 let C h = c print $ h 3 -- print c
いくつか問題があるが、小さいものからひとつずつ片付けていこう。
昨日までの改造による状況を整理:
いまの(動いていない)変換例は以下(sample100 の --ddump-core):
(Main.main :: (Prelude.IO ())) = ((((Prelude.>> :: ([Prelude.Monad TVar (Tyvar "t0" (Kfun Star Star))] :=> ((TVar (Tyvar "t0" (Kfun Star Star)) t1) -> ((TVar (Tyvar "t0" (Kfun Star Star)) t2) -> (TVar (Tyvar "t0" (Kfun Star Star)) t2))))) ${Prelude.IO Prelude.Monad}) ((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) "Hello!")) ((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) "World!"))
改造しようとして、まずリファクタして、trace を仕込みつつみていて気付いたのだけど、 辞書を適用した結果がまた辞書わたし形式になるような再帰は、 静的に解決できるとは限らない。ランタイムにまた辞書探してくるなんてことはできないので、 これは変だ。
この型がまちがっている >Prelude.IO%I.>> :: Forall [Kfun Star Star,Star,Star] ([Prelude.Monad a] :=> ((a b) -> ((a c) -> (a c))))
そちらを直そう。そうすると、tcBind に [Assump] を渡すのは不要だったな、 忘れないうちに戻そう。⇒ done.
trCDecl を変更して、DictDef に型シグネチャも格納するようにした。
今度は、renInstDecls でこの情報をもちいて、インスタンスメソッドの型シグネチャを出力するようにする。
DictDef に格納される型情報の例いくつか:
TypeSigDecl [Name {origName = ">>", namePos = (51,4), isConName = False}] (Just (AppTy (Tycon (Name {origName = "Monad", namePos = (48,7), isConName = True})) (Tyvar (Name {origName = "m", namePos = (48,13), isConName = False}))),FunTy (AppTy (Tyvar (Name {origName = "m", namePos = (51,13), isConName = False})) (Tyvar (Name {origName = "a", namePos = (51,15), isConName = False}))) (FunTy (AppTy (Tyvar (Name {origName = "m", namePos = (51,20), isConName = False})) (Tyvar (Name {origName = "b", namePos = (51,22), isConName = False}))) (AppTy (Tyvar (Name {origName = "m", namePos = (51,27), isConName = False})) (Tyvar (Name {origName = "b", namePos = (51,29), isConName = False}))))) TypeSigDecl [Name {origName = "show", namePos = (7,3), isConName = False}] (Just (AppTy (Tycon (Name {origName = "Show", namePos = (5,7), isConName = True})) (Tyvar (Name {origName = "a", namePos = (5,12), isConName = False}))),FunTy (Tyvar (Name {origName = "a", namePos = (7,11), isConName = False})) (ListTy (Tycon (Name {origName = "Char", namePos = (7,17), isConName = True}))))
各インスタンスメソッドに型宣言がつくようにすることで、IO.>> の型が多相になってしまっていた問題は解決。
以前、テストのうち6つ通らないが、それらは別の issue として、本件はクローズする。
sample149 を追加