Haskell:对`>> =`运算符的类型感到困惑

ice*_*man 3 monads haskell bind io-monad

我正在通过一些介绍性的Haskell材料,目前正在通过Monads.我从概念上理解>>=运算符的类型是:

(Monad m) => m a -> (a -> m b) -> m b.

在这种情况下,我很困惑为什么下面的代码工作,即为什么它不会导致类型不匹配:

main = getLine >>= \xs -> putStrLn xs
Run Code Online (Sandbox Code Playgroud)

因为我们知道getLine :: IO String,我认为它可以与类型函数"绑定" String -> IO String.但是putStrLn有不同的类型:putStrLn :: String -> IO ().

那么为什么Haskell允许我们使用>>=这两个函数呢?

bhe*_*ilr 14

让我们排列类型:

(>>=)    ::  m      a -> (     a ->  m  b) -> m b
getLine  :: IO String
putStrLn ::              (String -> IO ())
Run Code Online (Sandbox Code Playgroud)

在这里,我们有m = IO,a = Stringb = (),所以我们可以将这些替换为>>='s类型签名以获得最终类型签名

(>>=) :: IO String -> (String -> IO ()) -> IO ()
Run Code Online (Sandbox Code Playgroud)


Guv*_*nte 5

()是一个有效的类型(称为单位,请注意它只包含一个可能的非底值),并在定义中b.

a= Stringb= ()因此我们得到:

IO String -> (String -> IO ()) -> IO ()