Haskell 对每个位置的元组分别执行操作
我想分别对每个位置的元组执行操作。比如说Haskell 对每个位置的元组分别执行操作,haskell,mapping,tuples,Haskell,Mapping,Tuples,我想分别对每个位置的元组执行操作。比如说 pair_of_sums (a1,b1) (a2,b2) = (a1+a2, b1+b2) λ> fst (bimap (+) (+) (3,5)) 10 13 λ> snd (bimap (+) (+) (3,5)) 100 105 还是更一般 sum_and_multiplication (a1,b1) (a2,b2) = (a1+a2, b1*b2) 有没有办法把它缩短?比如: pair_of_sums = xxx (+) sum
pair_of_sums (a1,b1) (a2,b2) = (a1+a2, b1+b2)
λ> fst (bimap (+) (+) (3,5)) 10
13
λ> snd (bimap (+) (+) (3,5)) 100
105
还是更一般
sum_and_multiplication (a1,b1) (a2,b2) = (a1+a2, b1*b2)
有没有办法把它缩短?比如:
pair_of_sums = xxx (+)
sum_and_multiplication = yyy ((+),(*))
以下是它的工作原理:
f = ((uncurry (***) .) .) . (***)
f op1 op2 = uncurry (***) . (op1 *** op2)
f op1 op2 p1 p2 = uncurry (***) ((op1 *** op2) p1) p2
f op1 op2 (x1, y1) p2 = uncurry (***) ((op1 *** op2) (x1, y1)) p2
f op1 op2 (x1, y1) p2 = uncurry (***) (op1 x1, op2 y1) p2
f op1 op2 (x1, y1) (x2, y2) = (op1 x1 *** op2 y1) (x2, y2)
f op1 op2 (x1, y1) (x2, y2) = (op1 x1 x2, op2 y1 y2)
一种可能是使用包,包中有一些有用的方法和函数用于处理不同的类型,包括对
pair_of_sums = (<<.>>) . bimap (+) (+)
(本质上,~
只是告诉Haskell在这里要懒一点。这与我们的目的无关。)
在这种情况下,获取一对函数和一对函数,并将第一对中的每个函数映射到第二对的相应值上。对于这种用法,我们可以将其视为键入():(a->a',b->b')->(a,b)->(a',b')
)
我们可以再次查看此函数的源代码,了解此函数如何适用于(,)
实例:
(f, g) <<.>> (a, b) = (f a, g b)
这为我们提供了一对函数,将给定值添加到该对每个位置的原始值中。比如说
pair_of_sums (a1,b1) (a2,b2) = (a1+a2, b1+b2)
λ> fst (bimap (+) (+) (3,5)) 10
13
λ> snd (bimap (+) (+) (3,5)) 100
105
我们与()
的组合允许我们将这对函数转换为一个函数,它接受一对并给出一对(与我上面给出的类型签名相匹配)
把这些放在一起,我们可以更详细地了解调用中执行的减少对求和(3,5)(10100)
:
一对求和(3,5)(10100)
(().bimap(+)(+)(3,5)(10100)——对_和的定义
(\x->()(bimap(+)(+)x))(3,5)(10100)——的定义
()(bimap(+)(+)(3,5))--
(10100)——函数应用
bimap(+)(+)(3,5)(10100)——从前缀切换到中缀
(++)3、(++)5)(10100)——在为(,)实例应用bimap之后
(++)3 10,(++)5 100--(,)实例的()定义
(13,105)——应用(+)
这与Applicative
类型类的工作方式非常相似,但它与Bifunctor
一起工作,而不是Functor
(实际上,这就是为什么类型类()
属于Biapply
)bimap
类似于fmap
,()
类似于()
使用此技术定义这些函数的一个很酷的地方是,它们适用于所有类型构造函数,这些类型构造函数是
Biapply
的实例,而不仅仅是看起来像是overkill的经典定义的(,)
。
λ> fst (bimap (+) (+) (3,5)) 10
13
λ> snd (bimap (+) (+) (3,5)) 100
105
pair_of_sums (3, 5) (10, 100)
((<<.>>) . bimap (+) (+)) (3, 5) (10, 100) -- Definition of pair_of_sums
(\x -> (<<.>>) (bimap (+) (+) x)) (3, 5) (10, 100) -- Definition of (.)
(<<.>>) (bimap (+) (+) (3, 5)) --
(10, 100) -- Function application
bimap (+) (+) (3, 5) <<.>> (10, 100) -- Switch from prefix to infix
((+) 3, (+) 5) <<.>> (10, 100) -- After applying bimap for the (,) instance
((+) 3 10, (+) 5 100) -- Definition of (<<.>>) for the (,) instance
(13, 105) -- Apply (+)