# 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 へ。