运营商< - in haskell如何表现?

pee*_*ngh 1 haskell do-notation

我理解(有些)monad并理解运算符< - 将从monad中提取值.

但它如何适用于不同类型?

通常,我已经看到它被用于从IO monad中提取字符串.但是在下面的示例代码中,我无法看到它为什么在主要的第3行失败,抱怨它期待一种类型的IO int?编译器如何推断需要IO int?

它(<-)在multWithLog方法中做了什么?

import Control.Monad.Trans.Writer.Lazy

main = do
   putStrLn $ show $ logNumber 3 -- prints WriterT (Identity (3,["Got Number: 3"]))
   putStrLn $ show $ multWithLog -- prints WriterT (Identity (3,["Got Number: 3"]))
    _ <- logNumber 3 -- fails with Couldn't match type ‘WriterT [String] Data.Functor.Identity.Identity’ with ‘IO’
                    -- Expected type: IO Int
                    -- Actual type: Writer [String] Int
   putStrLn "test"


logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["Got Number: " ++ show x])

multWithLog :: Writer [String] Int
multWithLog = do
  a <- logNumber 3
  --b <- logNumber 5
  return a
Run Code Online (Sandbox Code Playgroud)

mel*_*ene 6

do块中的每个语句必须来自相同的monadic类型.

multWithLog = do
  a <- logNumber 3
  return a
Run Code Online (Sandbox Code Playgroud)

我们已经logNumber 3 :: Writer [String] Intreturn a :: (Monad m) => m Int(这是多态),所以整个事情typechecks为Writer [String] Int(带m = Writer [String],这是一个单子).

main = do
   putStrLn $ show $ logNumber 3
   putStrLn $ show $ multWithLog
    _ <- logNumber 3
   putStrLn "test"
Run Code Online (Sandbox Code Playgroud)

我们有putStrLn ... :: IO ()logNumber 3 :: Writer [String] Int.这是一个类型错误,因为Writer [String]它不一样IO.

根本原因是do块只是调用>>=和的句法糖>>.你main真的意味着

main =
   (putStrLn $ show $ logNumber 3) >>
   (putStrLn $ show $ multWithLog) >>
   logNumber 3 >>= \_ ->
   putStrLn "test"
Run Code Online (Sandbox Code Playgroud)

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

这要求类型m始终保持不变.