【问题标题】:Haskell: Confused about type of `>>=` operatorHaskell:对`>>=`运算符的类型感到困惑
【发布时间】:2014-10-14 16:32:27
【问题描述】:

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

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

在这种情况下,我很困惑为什么以下代码有效,即为什么它不会导致类型不匹配:

main = getLine >>= \xs -> putStrLn xs

既然我们知道getLine :: IO String,我假设它可以与String -> IO String 类型的函数“绑定”。但是putStrLn 属于不同类型:putStrLn :: String -> IO ()

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

【问题讨论】:

  • aStringmIOb()(单位或空元组)。因此,lambda 的类型是String -> IO ()

标签: haskell bind monads io-monad


【解决方案1】:

让我们排列类型:

(>>=)    ::  m      a -> (     a ->  m  b) -> m b
getLine  :: IO String
putStrLn ::              (String -> IO ())

这里有m = IOa = Stringb = (),所以我们可以将它们代入>>=的类型签名中,得到最终的类型签名

(>>=) :: IO String -> (String -> IO ()) -> IO ()

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • (它包含两个值,另一个是底部。;)
    【解决方案3】:

    既然我们知道getLine :: IO String,我假设它可以与String -> IO String 类型的函数“绑定”。

    你为什么会这样想?再看类型签名:

    (>>=) :: m a -> (a -> m b) -> m b
    

    左边是m a,右边是m b。尤其是中间的那位 a -> m b,表示传递给 >>= 的函数接受 a 并返回 m b。它没有说它必须返回m a,它说它可以是m b,其中b 是任何随机类型。它不必匹配a

    在您的示例中,lambda 函数采用 String 并返回 IO ()。所以a = Stringb = ()。这很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-17
      相关资源
      最近更新 更多