16

我只是写了这样的函数,map4只是因为它们看起来很有用:

map2 :: Functor f => (i -> a) -> (i -> b) -> f i -> f (a,b)
map2 f1 f2 = fmap $ \i -> (f1 i, f2 i)

在我继续之前,map8我想我会问一些标准模块中是否有类似的东西。Hayoo 似乎不知道任何具有上述签名的函数。

注意:我已经发现Control.Arrow.&&&将上述内容简化为:

map2 f1 f2 = fmap (f1 &&& f2)

但是对于超过两个的扇出似乎没有类似的功能。

4

2 回答 2

19

(->) i是一个应用函子,所以你可以(&&&)写成

f &&& g = (,) <$> f <*> g

你可以map3写成

map3 f1 f2 f3 = map ((,,) <$> f1 <*> f2 <*> f3)

除了它不短于

map3 f1 f2 f3 = map $ \i -> (f1 i, f2 i, f3 i)

但多亏了 Gabriel 的提示,这短了:

map3 f1 f2 f3 = map (liftA3 (,,) f1 f2 f3)
于 2013-06-12T21:29:16.817 回答
12

尽管您可以使用嵌套元组来模拟它,但没有超过两个扇出的标准函数:

f :: i -> a
g :: i -> b
h :: i -> c

f &&& g :: i -> (a, b)

(f &&& g) &&& h :: i -> ((a, b), c)

如果你不喜欢嵌套元组,那么你将不得不自己编写这个函数:

fanout3 :: (i -> a) -> (i -> b) -> (i -> c) -> i -> (a, b, c)
fanout3 f g h i = (f i, g i, h i)

就像您在问题中提到的那样,一旦您拥有这样的功能,您就可以使用map它:

map (fanout3 f g h) :: [i] -> [(a, b, c)]
于 2013-06-12T20:20:37.070 回答