使用带有两个列表的映射而不是一个.你能窝吗?

Nic*_*unt 7 mapping haskell

我需要运行一个多次接受两个参数的函数.我有两个包含这些参数的列表,我希望能够使用map或类似的东西用相应的args调用该函数.

我想调用的函数有这种类型:

runParseTest :: String -> String -> IO()
Run Code Online (Sandbox Code Playgroud)

列表创建如下:

-- 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]
Run Code Online (Sandbox Code Playgroud)

所以我们说names包含["test1.js", "test2.js", "test3.js"]libs包含["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]

我想这样称呼它们:

runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
Run Code Online (Sandbox Code Playgroud)

我知道我可以创建一个帮助函数,相当容易地做到这一点,但出于兴趣,是否可以在一行中使用map

这是我到目前为止所做的,但显然第一个论点总是"测试":

mapM_ (runParseTest "test") libs
Run Code Online (Sandbox Code Playgroud)

如果不清楚,我道歉.如有必要,我可以提供更多信息.

Ant*_*sky 16

这是使用Hoogle的好时机!Hoogle是一个搜索Haskell 类型的搜索引擎.例如,一个Hoogle查询用于(a -> b) -> [a] -> [b]提升map.在这里,你有一个类型的功能String -> String -> IO (); 你想要一个类型的功能(String -> String -> IO ()) -> [String] -> [String] -> IO ().Hoogle可以经常自己概括,但它在这里遇到麻烦,所以让我们帮忙吧:你只想要(a -> a -> IO ()) -> [a] -> [a] -> IO ()任何a.如果您为该类型签名进行Hoogle,则第一个结果zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()位于Control.Monad模块中,该模块完全符合您的要求.这是一系列功能的一部分,具有不同程度的通用性:

因此,在您的特定用例中,我们将进行一些额外的更改 - 以下内容:

import Data.List (isPrefixOf)

...

-- I got rid of `head` because it's a partial function, and I prefer `map` to
-- list comprehensions for simple things    
do files <- getDirectoryContents "tests/libraries"
   let names = filter (not . ("." `isPrefixOf`)) files
       libs  = map ("tests/libraries/" ++) names
   zipWithM_ runParseTest names libs
Run Code Online (Sandbox Code Playgroud)


ДМИ*_*КОВ 11

所以我们假设名称包含["test1.js", "test2.js", "test3.js"] 和libs包含["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]

我想这样称呼它们:

runParseTest "test1.js" "tests/libraries/test1.js" runParseTest "test2.js" "tests/libraries/test2.js" runParseTest "test3.js" "tests/libraries/test3.js"

可以这样做zip:

map (\(a,b) -> runParseTest a b) $ zip names libs
Run Code Online (Sandbox Code Playgroud)

或许uncurry runParseTest:

 map (uncurry runParseTest) $ zip names libs
Run Code Online (Sandbox Code Playgroud)

或者zipWith:

 zipWith runParseTest names libs
Run Code Online (Sandbox Code Playgroud)

就像Ozgur所说,monad有一些类似物:

> :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 ()
Run Code Online (Sandbox Code Playgroud)