Haskell,forM - 为什么这段代码returns会出现这样的结果?

Haskell, forM - why this code returns such result?

我看到的时候很惊讶:

forM [5,6] (\x -> x:[7])
[[5,6],[5,7],[7,6],[7,7]]

我想得到[[5,7], [6,7]]。我知道可以使用 map 获取它,但我现在正在学习 monads。
我进行下一步,然后尝试:

forM [5,6] (\x -> print x)
5
6
[(),()]

这是什么意思? [(), ()]至少是奇怪的。你能解释一下这个问题吗?

关于你的奇怪[(),()]

对于第二个,请记住:printShow a => a -> IO ()(并且具有使用 show 打印出值的副作用)

现在

forM [5,6] print -- same as yours
= mapM print [5,6]
= sequence $ fmap print [5,6]
= sequence [print 5, print 6]

现在是副作用:IO monad 中的 sequence 将一个接一个地计算

但是 结果 [(),()](记住:sqeuence :: [IO a] -> IO [a]

所以你首先得到副作用(56 打印在换行符上)然后是这个计算的结果 [(),()]

摆脱它:

你可以通过使用 forM_ 来摆脱这个(这将返回 ()):

> import Control.Monad(forM_)
> forM_ [5,6] print
5
6

关于 list-monad

你可以从这里看出为什么第一个:

forM [5,6] (\x -> x:[7])
= mapM (\x -> x:[7]) [5,6]
= sequence (fmap (\...) [5,6])
= sequence [[5,7],[6,7]]
= [[5,6],[5,7],[7,6],[7,7]]

记住——list-monad 基本上是在那里做叉积

print 5 是一个 IO () 类型的值,一个执行 I/O 的操作,最后 return 是一个 () 类型的值(有只有一个这样的值:()).

forM list print 执行 print list 中的每个值,并且 returns 他们的列表 return 值。这是一个 () 的列表,这就是为什么你看到最后一个 [(),...,()] 的原因。相比之下 forM_ list print 不会是 return 的列表结果,而是单个 ()。

请注意 GHCi 特例 IO () 操作,因为 GHCi 不会打印最终的 () 结果。例如,情况并非如此。 IO [()] 个操作,因此 GHCi 将在最后打印最终列表。