簡體   English   中英

haskell中的運算符<-表現如何?

[英]How does the operator <- in haskell behave?

我了解(某種程度上)單子,並且理解運算符<-將從單子中提取值。

但是它如何與不同類型一起使用?

通常,我已經看到它用於從IO monad提取字符串。 但是在下面的示例代碼中,無法看到為什么它在主第三行中失敗,抱怨說它期望使用IO int類型? 編譯器如何推斷需要IO int?

另外,在multWithLog方法中( <- )有什么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

do塊中的每個語句do必須來自同一單子類型。

multWithLog = do
  a <- logNumber 3
  return a

我們有logNumber 3 :: Writer [String] Intreturn a :: (Monad m) => m Int (它是多態的),因此整個類型都作為Writer [String] Int (其中m = Writer [String] ,這是一個單子)。

main = do
   putStrLn $ show $ logNumber 3
   putStrLn $ show $ multWithLog
    _ <- logNumber 3
   putStrLn "test"

我們有putStrLn ... :: IO ()logNumber 3 :: Writer [String] Int 這是類型錯誤,因為Writer [String]IO

根本原因是do塊只是>>=>>調用的語法糖。 例如,您的main意思是

main =
   (putStrLn $ show $ logNumber 3) >>
   (putStrLn $ show $ multWithLog) >>
   logNumber 3 >>= \_ ->
   putStrLn "test"

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

這要求類型m始終保持相同。

注意諸如以下的措辭

從monad提取值

單聲道不包含“ a”值。 例如, Maybe包含零或一個值。 列表( [] )包含多個值。 有關更多詳細信息,請參見此答案

例如,在列表的情況下, <-運算符一次提取一個列表值。

使用do表示法時,提取的所有值必須屬於同一Monad 在OP中,由於putStrLn返回IO ()值,因此編譯器推斷出該MonadIO

另一方面, logNumber返回Writer [String] Int值,盡管這也是Monad實例,但它與IO 因此,該代碼不會鍵入檢查。

簡化事情。 這是兩個事實

  1. Writer [String]實際上是monad,因此Writer [String] Int可以看作是m Int
  2. do塊中的每個動作都應在同一monad中發生。

main函數中,編譯器的推理如下:

  1. 我在IO monad中工作,因為putStrLn ...IO ()類型
  2. 讓我計算_ <- logNumber 3 由於我在IO monad中,因此logNumber 3應該是IO WhatEver
  3. logNumber 3實際上是類型m Int的單子值
  4. 等待! mWriter [String] monad,而不是IO monad
  5. 打印一條錯誤消息,指出Writer [String] Int不正確,應為IO Int

這就是IO Int來源。 我只是想在這里進行教學。 查看@melpomene的答案以獲取完整說明

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM