使用具有两个列表而非一个列表的地图。你可以窝窝吗? [英] Using map with two lists rather than one. Can you nest?
问题描述
我需要运行一个多次使用两个参数的函数。我有两个包含这些参数的列表,我希望能够使用 map
或类似的东西来调用具有相应参数的函数。
我想要调用的函数有这样的类型:
runParseTest :: String - >字符串 - > IO()
这些列表是这样创建的:
- 获取库目录中的文件列表
文件< - getDirectoryContentstests / libraries
- 过滤掉..和 。并添加路径
let names = filter(\ x - > head x / ='。')files
let libs = [tests / libraries /++ f | f < - $ name>
因此可以说名称
包含 [test1.js,test2.js,test3.js]
和 libs
包含 [tests / libraries / test1.js,tests / libraries / test2.js,tests / libraries / test3.js]
我想这样称呼他们:
runParseTesttest1.js tests / libraries / test1.js
runParseTesttest2.jstests / libraries / test2.js
runParseTesttest3.jstests / libraries / test3.js
我知道我可以创建一个辅助函数,它可以很容易地完成这项工作,但出于兴趣,是否可以在一行使用 map
?
这是我迄今为止的内容,但显然第一个参数始终是test :
mapM_(runParseTesttest)libs
如果不清楚,我很抱歉。我可以提供更多的信息,如果有必要的话。
c> [test1.js,test2.js,test3.js]
和libs包含[tests / libraries / test1.js ,tests / libraries / test2.js,tests / libraries / test3.js]
我想给他们打电话这:
runParseTesttest1.jstests / libraries / test1.js
runParseTesttest2.jstests / libraries / test2.js
runParseTesttest3.jstests / libraries / test3。 js
可以用 zip
:
$ $ p $ map(\(a,b) - > runParseTest ab)$ zip名称库lib
也许 uncurry runParseTest
:
map(uncurry runParseTest)$ zip名称库
或与 zipWith
:
zipWith runParseTest names libs
像Ozgur 表示,monads有一些类似物:
> :t zipWithM
zipWithM :: Monad m => (a - > b - > m c) - > [a] - > [b] - > m [c]
> :t zipWithM_
zipWithM_ :: Monad m => (a - > b - > m c) - > [a] - > [b] - > m()
I need to run a function that takes two arguments several times. I have two lists containing these arguments and I'd like to be able to use map
or something similar to call the function with the corresponding args.
The function I want to call has this type:
runParseTest :: String -> String -> IO()
The lists are created like this:
-- Get list of files in libraries directory
files <- getDirectoryContents "tests/libraries"
-- Filter out ".." and "." and add path
let names = filter (\x -> head x /= '.') files
let libs = ["tests/libraries/" ++ f | f <- names]
So lets say that names
contains ["test1.js", "test2.js", "test3.js"]
and libs
contains ["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]
I want to call them like this:
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
I know I could create a helper function that does this fairly easily, but out of interest, is it possible to do in one line using map
?
This is what I have so far, but obviously the first argument is always "test":
mapM_ (runParseTest "test") libs
I apologise if this is unclear. I can provide more info if necessary.
So lets say that names contains
["test1.js", "test2.js", "test3.js"]
and libs contains["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]
I want to call them like this:
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
It's possible to do that with zip
:
map (\(a,b) -> runParseTest a b) $ zip names libs
Or maybe uncurry runParseTest
:
map (uncurry runParseTest) $ zip names libs
Or with zipWith
:
zipWith runParseTest names libs
And like Ozgur said, there are some analogues for monads:
> :t zipWithM
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
> :t zipWithM_
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
这篇关于使用具有两个列表而非一个列表的地图。你可以窝窝吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!