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
[(),()]
这是什么意思? [(), ()]
至少是奇怪的。你能解释一下这个问题吗?
关于你的奇怪[(),()]
对于第二个,请记住:print
是 Show 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]
)
所以你首先得到副作用(5
和 6
打印在换行符上)然后是这个计算的结果 [(),()]
摆脱它:
你可以通过使用 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 将在最后打印最终列表。
我看到的时候很惊讶:
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
[(),()]
这是什么意思? [(), ()]
至少是奇怪的。你能解释一下这个问题吗?
关于你的奇怪[(),()]
对于第二个,请记住:print
是 Show 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]
)
所以你首先得到副作用(5
和 6
打印在换行符上)然后是这个计算的结果 [(),()]
摆脱它:
你可以通过使用 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 将在最后打印最终列表。