Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 使用带有两个列表而不是一个列表的映射。你会筑巢吗?_Haskell_Mapping - Fatal编程技术网

Haskell 使用带有两个列表而不是一个列表的映射。你会筑巢吗?

Haskell 使用带有两个列表而不是一个列表的映射。你会筑巢吗?,haskell,mapping,Haskell,Mapping,我需要运行一个多次使用两个参数的函数。我有两个包含这些参数的列表,我希望能够使用map或类似的东西来调用带有相应参数的函数 我要调用的函数具有以下类型: runParseTest :: String -> String -> IO() 创建的列表如下所示: -- Get list of files in libraries directory files <- getDirectoryContents "tests/libraries" -- Filter out ".."

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

我要调用的函数具有以下类型:

runParseTest :: String -> String -> IO()
创建的列表如下所示:

-- 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]
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
我知道我可以很容易地创建一个助手函数,但是出于兴趣,是否可以使用
map
在一行中创建

到目前为止,这就是我的观点,但显然第一个论点总是“测试”:

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

假设名称包含
[“test1.js”、“test2.js”、“test3.js”]
libs包含
[“tests/libraries/test1.js”、“tests/libraries/test2.js”、“tests/libraries/test3.js”]

我想这样称呼他们:

-- 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]
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.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
或者可能
未经修正的runParseTest

 map (uncurry runParseTest) $ zip names libs
或使用
zipWith

 zipWith runParseTest names libs
如前所述,单子有一些类似物:

> :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 ()
你在找我

你说你可以写一个助手函数来实现这一点。这意味着您知道要查找的函数的类型。在这种情况下,您可以使用


(试试:Monad m=>[a]->[b]->m())

这是一个很好的使用时机!Hoogle是一个搜索Haskell类型的搜索引擎。例如,一个对的Hoogle查询就会出现。这里有一个类型为
String->String->IO()
的函数;您需要类型为
(String->String->IO())->[String]->[String]->IO()
的函数。Hoogle通常可以自己进行泛化,但是它在这里遇到了问题,所以让我们来帮助它:对于任何
a
,您只需要
(a->a->IO())->[a]->[a]->IO()
。如果需要,第一个结果将出现在模块中,该模块正是您想要的。这是一系列功能的一部分,具有不同程度的通用性:

  • ,它将两个列表配对,截断较短的一个
  • ,它对两个列表中的每个元素运行提供的函数
    zip=zipWith(,)
  • ,类似于单子中的
    zipWith
    zipWithM f xs ys=序列$zipWithf xs ys
  • ,类似于zipWithM,但丢弃其结果
    zipWithM_fxs ys=zipWithM f xs ys>>return()=sequence_$zipWith f xs ys
  • ,我相信您可以了解其功能:-)
  • ,类似于三个列表上的
    zipWith
    zipWith3=zip(,)
  • 一系列
    zipN
    zipWithN
    函数,通过
    zip7
    /
    zipWith7
    上升。(可以说,这是从as
    zip1
    和as
    zipWith1
    开始的,这就是您的问题的来源。)
  • 以及最一般的应用函子。给定一些列表,
    xs1
    xsN
    ,然后
    runZipList$f ZipList xs1 ZipList xs2。。。ZipList xsN=runZipList$liftAN f(ZipList xs1)。。。(ZipList xsN
    )的行为与zipWithN f xs1一样。。。xsN
因此,在您的特定用例中,我们将进行一些额外的更改,如下所示:

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
导入数据列表(isPrefixOf)
...
--我去掉了'head',因为它是一个偏函数,我更喜欢'map',而不是
--列出对简单事物的理解

do files在等待答案的过程中,我根据
map
mapM
的源代码,创建了一个名为
map2M\
的新函数,并创建了自己的解决方案:

map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
map2 _ [] _          = []
map2 _ _ []          = []
map2 f (a:as) (b:bs) = f a b : map2 f as bs

map2M_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
map2M_ f as bs =  sequence_ (map2 f as bs)

这就是我要找的。实际上,我已经编写了一个名为
map2M\uu
的新函数,我将发布该函数,但我确信这是一种“正确”的方法。