简体   繁体   中英

Is it possible in Haskell to apply the function putStrLn to every element of a list of Strings, have it print to the screen, while being non recursive

I am trying to make a function that takes a list of strings and executes the command putStrLn or print (I think they are basically equivalent, please correct me if I am wrong as I'm still new to Haskell) to every element and have it printed out on my terminal screen. I was experimenting with the map function and also with lambda/anonymous functions as I already know how to do this recursively but wanted to try a more complex non recursive version. map returned a list of the type IO() which was not what I was going for and my attempts at lambda functions did not go according to plan. The basic code was:

test :: [String] -> something
test x = map (\a->putStrLn a) x -- output for this function would have to be [IO()]

Not entirely sure what the output of the function was supposed to be either which also gave me issues.

I was thinking of making a temp :: String variable and have each String appended to temp and then putStrLn temp but was not sure how to do that entirely. I though using where would be viable but I still ran into issues. I know how to do this in languages like java and C but I am still quite new to Haskell. Any help would be appreciated.

There is a special version of map that works with monadic functions, it's called mapM :

test :: [String] -> IO [()]
test x = mapM putStrLn x

Note that this way the return type of test is a list of units - that's because each call to putStrLn returns a unit, so result of applying it to each element in a list would be a list of units. If you'd rather not deal with this silliness and have the return type be a plain unit, use the special version mapM_ :

test :: [String] -> IO ()
test x = mapM_ putStrLn x

I was thinking of making a temp :: String variable and have each String appended to temp and then putStrLn temp

Good idea. A pattern of "render the message" then a separate "emit the message" is often nice to have long term.

test xs = let temp = unlines (map show xs)
          in putStrLn temp

Or just

test xs = putStrLn (unlines (show <$> xs))

Or

test = putStrLn . unlines . map show

Not entirely sure what the output of the function was supposed to be either which also gave me issues.

Well you made a list of IO actions:

test :: [String] -> [IO ()]
test x = map (\a->putStrLn a) x

So with this list of IO actions when do you want to execute them? Now? Just once? The first one many times the rest never? In what order?

Presumably you want to execute them all now. Let's also eta reduce (\\a -> putStrLn a) to just putStrLn since that means the same thing:

test :: [String] -> IO ()
test x = sequence_ (map (\a->putStrLn a) x)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM