繁体   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