迭代打印列表中的每个整数 [英] Iteratively printing every integer in a List

查看:152
本文介绍了迭代打印列表中的每个整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个整数列表 l = [1,2]



我想打印to stdout



执行 print l 产生 [1,2]



假设我想打印没有花括号的列表



map print l 产生

  (显示(IO()))
在一个交互式GHCi命令中添加一个实例声明:print它

`:t print

  print :: Show a => a  - > IO()

所以,当我认为这会起作用时,我继续尝试:

  map putStr $ map show l 

由于我怀疑从Integer到String的类型不匹配是怪罪。这产生了与上面相同的错误信息。



我意识到我可以做一些事情,比如将列表连接成一个字符串,但是我希望尽可能避免这种情况。 / p>

发生了什么事?我怎样才能做到这一点,而不需要从List的元素构造一个字符串?

解决方案

假设给出了一个 xs :: [a] 和函数 f :: Monad m => a - > m b 。您希望将函数 f 应用于 xs 的每个元素,生成一系列操作,然后对这些操作进行排序。下面是我将如何构建一个函数,将其称为 mapM ,这是做到这一点的。在基本情况下, xs = [] 是空列表,我们只返回 [] 。在递归的情况下, xs 的形式为 x:xs 。首先,我们要将 f 应用于 x ,给出动作 fx :: mb 。接下来,我们要在 xs 上递归调用 mapM 。执行第一步的结果是一个值,比如 y ;执行第二步的结果是一个值列表,比如 ys 。因此,我们将 y ys 收集到一个列表中,然后将它们返回到monad中:

  mapM :: Monad m => (a  - > m b) - > [a]  - > m [b] 
mapM f [] = return []
mapM f(x:xs)= f x>> = \ y - > mapMf ys>> = \ s - >返回(y:ys)

现在我们可以映射一个像 print ,它在 IO monad中返回一个动作,并在要打印的值列表中: mapM print [1..10 ] 正好是从1到10的整数列表。然而,存在一个问题:我们并不特别关心收集印刷操作的结果;我们主要关心他们的副作用。而不是返回 y:ys ,我们只需返回()

  mapM_ :: Monad m => (a  - > m b) - > [a]  - > m()
mapM_ f [] = return()
mapM_ f(x:xs)= f x>> mapM_ f xs

请注意 mapM 和<可以使用序列序列_ 定义code> mapM _ 标准库中的函数,这些函数正是他们的名字所暗示的。如果您查看 Control.Monad mapM mapM _ 的源代码c $ c>,你会看到它们以这种方式实现。


Say I have a List of integers l = [1,2]

Which I want to print to stdout.

Doing print l produces [1,2]

Say I want to print the list without the braces

map print l produces

No instance for (Show (IO ())) arising from a use of `print'
Possible fix: add an instance declaration for (Show (IO ()))
In a stmt of an interactive GHCi command: print it

`:t print

print :: Show a => a -> IO ()

So while I thought this would work I went ahead and tried:

map putStr $ map show l

Since I suspected a type mismatch from Integer to String was to blame. This produced the same error message as above.

I realize that I could do something like concatenating the list into a string, but I would like to avoid that if possible.

What's going on? How can I do this without constructing a string from the elements of the List?

解决方案

Suppose you're given a list xs :: [a] and function f :: Monad m => a -> m b. You want to apply the function f to each element of xs, yielding a list of actions, then sequence these actions. Here is how I would go about constructing a function, call it mapM, that does this. In the base case, xs = [] is the empty list, and we simply return []. In the recursive case, xs has the form x : xs. First, we want to apply f to x, giving the action f x :: m b. Next, we want recursively call mapM on xs. The result of performing the first step is a value, say y; the result of performing the second step is a list of values, say ys. So we collect y and ys into a list, then return them in the monad:

mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f []       = return []
mapM f (x : xs) = f x >>= \y -> mapM f ys >>= \ys -> return (y : ys)

Now we can map a function like print, which returns an action in the IO monad, over a list of values to print: mapM print [1..10] does precisely this for the list of integers from one through ten. There is a problem, however: we aren't particularly concerned about collecting the results of printing operations; we're primarily concerned about their side effects. Instead of returning y : ys, we simply return ().

mapM_ :: Monad m => (a -> m b) ->[a] -> m ()
mapM_ f []       = return ()
mapM_ f (x : xs) = f x >> mapM_ f xs

Note that mapM and mapM_ can be defined without explicit recursion using the sequence and sequence_ functions from the standard library, which do precisely what their names imply. If you look at the source code for mapM and mapM_ in Control.Monad, you will see them implemented that way.

这篇关于迭代打印列表中的每个整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆