# 056: retint.hs で cannot resolve ambiguity [↑up](bunny_notes) - issued: 2020-05-04 - 分類: A サンプルコードが fail - status: Closed (2020-05-06) ## 概要 retint.hs をコンパイルすると型推論で失敗、cannot resolve ambiguity となる。 retint.hs: $$
{ strlen "" = 0 strlen (c:cs) = 1 + strlen cs main = return (strlen "Haskell") $$} ## 調査ログ ### 2020-05-06 このエラーは、Typing で発生している(ので、後段の DictPass などの問題ではない)。 たしかに、なんの型注釈もないと、return が何モナドのインスタンスかわからないだろう。 - 型注釈なし → errror: cannot resolve ambiguity - main :: IO a とする → error: context too weak - main :: IO Int → OK - main :: IO () → error: context reduction main に型注釈がない場合には、以下のように最後に >> return () を追加しつつ、 型注釈 main :: IO () をつければ、仕様(main は IO t を計算して最後に t をすてる) が満たせるのでは。 $${ strlen "" = 0 strlen (c:cs) = 1 + strlen cs main :: IO () main = do { return (strlen "Haskell") } >> return () $$} なお、main :: [Int] のように IO t でない型注釈を明に書いてもはじかれるので、 そういうチェックは必要。 (main :: ty) main = e を main :: IO () main = e >> return () または、 main :: IO () main = (e :: ty) >> return () に変形してやれば、ty が IO t の形をしていることのチェックも含め実現できそう。 ⇒ 変形しなくても、型検査器に制約をしらせるだけであれば、以下のように 特別な関数 main' を追加してやるだけで OK っぽい。 $${ strlen "" = 0 strlen (c:cs) = 1 + strlen cs main = return (strlen "Haskell") main' :: IO () main' = main >> return () $$} このようなダミー宣言を Semant で付け加えるようにして、期待通りに動作した。 retint.hs は sample179.hs へ。