2

我有一个功能,我想用几组输入进行测试。假设函数是

f :: a -> b -> c

现在我有两个输入列表:

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

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

我最近的尝试是

map f inputA <$> inputB

这给出了以下错误:

无法匹配预期类型a0 -> b0' with actual type[b1]'
在调用map' 的返回类型中应用于太多参数 在map f inputA'的第一个参数中 在表达式中: map f inputA inputBmap'
Probable cause:

(<$>)', namely

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

额外的想法:

map f inputA :: [b -> c]

我认为这是正确的方向。现在我需要将每个函数映射到inputB.

为了澄清,我想将i第 th 函数映射到map f inputA第thi个输入列表中inputB以获得结果outputC :: [[c]]

4

4 回答 4

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]]
于 2013-10-05T07:02:30.833 回答
3

使用列表推导一切都很容易,

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   where  c' (a,b) = 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-reductiong = (zipWith . (map .))但这可能不容易理解。这被进一步混淆为zipWith <$> (map <$>)zipWith <$> ((<$>) <$>)

或者,我们可以使用来自as的类型ZipListControl.Applicative

           = zipWith (map . f) xs yss
           = getZipList $ liftA2 (map . f)    (ZipList xs)    (ZipList yss)
           = getZipList $ pure   (map . f) <*> ZipList xs  <*> ZipList yss
           = getZipList $        (map . f) <$> ZipList xs  <*> ZipList yss
           = getZipList $       map <$> (f <$> ZipList xs) <*> ZipList yss
于 2013-10-05T10:44:52.433 回答
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> 

IE

fancyZipMap :: (a -> b -> c) -> [a] -> [[b]] -> [[c]]
fancyZipMap f xs yys = map (\(x, ys) -> map (f x) ys) $ zip xs yys
于 2013-10-05T06:44:41.550 回答
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)]]
于 2013-10-05T05:54:26.343 回答