IO Monad示例

时间:2015-06-18 03:19:16

标签: haskell

考虑以下IO代码:

ghci> let x = return 100 :: IO Int

ghci> :t do { a <- x; print a; return 500 }
do { a <- x; print a; return 500 } :: Num b => IO b

我对do notation / bind的理解是编译器将强制执行以下签名:

ghci> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b

在上面的例子中,我的理解是:

  • x的类型为IO Int
  • print a的类型为IO ()
  • return 500的类型为Num b => IO b

在我看来,IO ()不符合类型Num b => IO b。此外,正如我所理解的,IO Int不符合Num b => IO b

如果这个观察是有效的,那么为什么这个代码会编译?每个行(即>>=)是否必须符合m b,其中m等于IO而b等于Num b => b

2 个答案:

答案 0 :(得分:3)

您发布的代码涉及以下内容。

x >>= (\a ->
print a >>
return 500)

或者,扩展(>>)

的定义
x       >>= (\a ->
print a >>= (\_ ->
return 500))

然后,您可以看到,在(>>=)的不同来电中,ab类型不一定相同。说(>>=) :: Monad m => m a -> (a -> m b) -> m b

    第一次调用中的
  • x的类型为IO Int\a -> print a >>= (\_ -> return 500)的类型为Num c => Int -> IO c,因此我的类型签名中的a为{ {1}}为(>>=)Intbc限制)。

  • 在第二个电话中:Num的类型为print a,而IO ()的类型为\_ -> return 500Num c => () -> IO c部分是通过尝试推断的匹配()的签名,因此(>>=)的类型签名中的a(>>=),而()b(仍为c限制。

答案 1 :(得分:1)

do { a <- x; print a; return 500 }相当于(return 100 :: Int) >>= print >> return 500

>>的签名为(>>) :: Monad m => m a -> m b -> m b,与所见内容同步。