![](/img/trans.png)
[英]How does HOpenGL behave with regards to other threads and TChans in 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] Int
并return 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 ()
值,因此编译器推断出该Monad
为IO
。
另一方面, logNumber
返回Writer [String] Int
值,尽管这也是Monad
实例,但它与IO
。 因此,该代码不会键入检查。
简化事情。 这是两个事实
Writer [String]
实际上是monad,因此Writer [String] Int
可以看作是m Int
do
块中的每个动作都应在同一monad中发生。 在main
函数中,编译器的推理如下:
IO
monad中工作,因为putStrLn ...
是IO ()
类型 _ <- logNumber 3
。 由于我在IO
monad中,因此logNumber 3
应该是IO WhatEver
logNumber 3
实际上是类型m Int
的单子值 m
是Writer [String]
monad,而不是IO
monad Writer [String] Int
不正确,应为IO Int
这就是IO Int
来源。 我只是想在这里进行教学。 查看@melpomene的答案以获取完整说明
希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.