do块中的返回类型

use*_*996 3 monads haskell types return

我正在尝试理解Haskell中的Monads,在我无数次使用代码的实验中遇到过这样的事情:

f2 = do   
  return "da"
Run Code Online (Sandbox Code Playgroud)

并且它不想编译有关类型的巨大错误.我认为唯一重要的部分是:

 No instance for (Monad m0) arising from a use of return'
The type variable `m0' is ambiguous  
Run Code Online (Sandbox Code Playgroud)

那么我已将我的代码更改为:

 f2 = do   
 return "da"  :: IO [Char]  
Run Code Online (Sandbox Code Playgroud)

而且效果非常好.但是当我试图弄乱一点并将类型更改为IO Int时再次出现错误.那么为什么这种类型实际上不是"含糊不清"?当我在返回之前添加一些内容时:

f2 = do   
  putStrLn "das"  
  return 2
Run Code Online (Sandbox Code Playgroud)

然后我不必指定返回的类型.那么有人可以解释我到底发生了什么吗?另外为什么在第一种情况下返回输出"da"?不是没有""?

Dan*_*zer 8

首先让我们指出

do
  return a
Run Code Online (Sandbox Code Playgroud)

完全一样

return a
Run Code Online (Sandbox Code Playgroud)

现在,问题是return有类型

return :: Monad m => a -> m a
Run Code Online (Sandbox Code Playgroud)

当你有一个像这样的声明

foo = bar
Run Code Online (Sandbox Code Playgroud)

哪里foo没有参数haskell使它"单态".这样做的结果是Haskell无法猜测是什么m,也不会概括它,所以你需要一个显式的类型签名.最普遍的是

f2 :: Monad m => m String
f2 = return "das"
Run Code Online (Sandbox Code Playgroud)

但你也可以使用IO或任何其他monad

f2 :: IO String
Run Code Online (Sandbox Code Playgroud)

最后,在你的最后一个例子中,既然你要返回2,你必须给出一个类型签名,表明你正在返回某种数字,比如

 f2 :: IO Integer
Run Code Online (Sandbox Code Playgroud)


wit*_*wit 5

这是已知的Monomorphism_restriction

使用签名

f2 :: Monad m => m String
f2 = do   
  return "da"
Run Code Online (Sandbox Code Playgroud)

或使用语言扩展:

{-# LANGUAGE NoMonomorphismRestriction #-}
f2 = do   
  return "da"
Run Code Online (Sandbox Code Playgroud)

获得有效的代码