将函数映射到两个输入列表

时间:2013-10-05 05:36:07

标签: haskell

我有一个功能,我想用几组输入进行测试。让我们说功能是

f :: a -> b -> c

现在我有两个输入列表:

inputA :: [a]
inputB :: [[b]]

对于inputA !! i,我想为f $ input !! i列表中的每个元素评估inputB !! i。我知道我需要map的几个应用程序才能做到这一点,但我很难绕过解决方案。

我最近的尝试是

map f inputA <$> inputB

会出现以下错误:

  

无法匹配预期类型a0 -> b0' with actual type [b1]&#39;
      在map'
Probable cause:
地图&#39;的调用的返回类型中适用于太多的论点
      在(<$>)', namely map f inputA&#39;的第一个参数中       在表达式中:map f inputA inputB

我应该如何解决这个问题?我不一定想要一个完整的解决方案。一个有用的方向推(或甚至推)肯定会受到赞赏。

其他想法:

map f inputA :: [b -> c]

我认为这是正确的方向。现在我需要在inputB

中的每个输入列表上映射每个函数

为了澄清,我想将i map f inputA函数映射到i的{​​{1}}输入列表中,以获得结果inputB

4 个答案:

答案 0 :(得分:6)

您可以使用zipWith

Prelude> let a = [1,2,3]
Prelude> let b = [[1,2,3],[4,5,6],[7,8,9]]
Prelude> zipWith (\a' bl -> map (+a') bl)  a b
[[2,3,4],[6,7,8],[10,11,12]]

答案 1 :(得分:2)

列表推导一切都很简单:

g f xs yss = [ [f x y | y <- ys] | (x,ys) <- zip xs yss]
           = [ map    (f x)  ys  | (x,ys) <- zip xs yss]
           = [ map     fx    ys  | (fx,ys) <- zip (map f xs) yss]
           = zipWith map (map f xs) yss

           = [ (map . f) x   ys  | (x,ys) <- zip xs yss]
           = zipWith (map . f) xs yss

nponeccop在评论中首先显示的最后一个,并在其他答案中暗示;我们可以通过使用代码转换来获取它

map c $ zip a b    == zipWith c a b
map (c a) b        == (map . c) a b
\a b-> map (c a) b ==  map . c

似乎你也试图找到它的无点版本:

           = zipWith (map . f) xs yss
           = (zipWith . (map .)) f xs yss

所以通过eta-reduction g = (zipWith . (map .)),但这可能不容易理解。这被进一步混淆为zipWith <$> (map <$>)甚至zipWith <$> ((<$>) <$>)

或者,我们可以使用the ZipList type from Control.Applicative作为

           = zipWith (map . f) xs yss
           = getZipList $ pure (map . f)   <*> ZipList xs  <*> ZipList yss
           = getZipList $      (map . f)   <$> ZipList xs  <*> ZipList yss
           = getZipList $       map <$> (f <$> ZipList xs) <*> ZipList yss

答案 2 :(得分:1)

如果我正确理解你,可以这样:

mapNested :: (a -> b -> c) -> [a] -> [[b]] -> [[c]]
mapNested f [] _ = []
mapNested f _ [] = []
mapNested f (x:xs) ys = concatMap (map (f x)) ys : mapNested f xs ys

Main> mapNested (+) [1, 2, 3] [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[2,3,4,5,6,7,8,9,10],[3,4,5,6,7,8,9,10,11],[4,5,6,7,8,9,10,11,12]]

如果这不是你想要的,你能提供一个示例输入和输出吗?

修改

或者这就是你想要的?

mapNested :: (a -> b -> c) -> [a] -> [[b]] -> [[c]]
mapNested f xs = zipWith map (map f xs)

Main> mapNested (,) [1, 2, 3] [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[(1,1),(1,2),(1,3)],[(2,4),(2,5),(2,6)],[(3,7),(3,8),(3,9)]]

答案 3 :(得分:1)

如果我理解正确,这就是你需要的:

Prelude> let f x y = x + y
Prelude> let xs = [1, 2, 3, 4, 5]
Prelude> let ys = [[1, 2], [3, 4, 5], [6, 7], [8], [9, 10]]
Prelude> map (\(x, ys) -> map (f x) ys) $ zip xs ys
[[2,3],[5,6,7],[9,10],[12],[14,15]]
Prelude> 

fancyZipMap :: (a -> b -> c) -> [a] -> [[b]] -> [[c]]
fancyZipMap f xs yys = map (\(x, ys) -> map (f x) ys) $ zip xs yys