无点的元组添加


16

表达功能的最短方法是什么

f(a,b)(c,d)=(a+c,b+d)

用无点表示法?

pointfree.io给了我们

uncurry (flip flip snd . (ap .) . flip flip fst . ((.) .) . (. (+)) . flip . (((.) . (,)) .) . (+))

只需一点点工作就可以缩短到

uncurry$(`flip`snd).((<*>).).(`flip`fst).((.).).(.(+)).flip.(((.).(,)).).(+)

为76个字节。但这似乎还是真的对于如此简单的任务来说漫长而复杂。有什么方法可以将成对加法表示为较短的无点函数?

为了清楚理解我所说的无点,函数的无点声明涉及获取现有函数和运算符,并以创建所需函数的方式将它们相互应用。反引号,括号内文字值([]0[1..3]等)允许的,但像关键字wherelet不是。这表示:

  • 您不得分配任何变量/功能

  • 您不得使用lambda

  • 您可能无法导入

这是CMC时的相同问题


9
我从来不明白为什么当它实际上充满点时被称为“ 点”。:P
Xcoder先生17年


5
可惜我们不允许导入最好的Haskell软件包,否则解决方案就是(+)***(+)
Silvio Mayolo

2
一个主意:(+)<$>([1],2)<*>([3],4)([1,3],6)
xnor

2
我花了一些时间尝试利用xnor的技巧来制定一个好的解决方案……但是最终我得到了这个垃圾。我什至不知道为什么有时我会尝试...
totallyhuman

Answers:



8

44字节

-8个字节感谢ØrjanJohansen。-3个字节,感谢Bruce Forte。

(.).flip(.)<*>(zipWith(+).)$mapM id[fst,snd]

在线尝试!

转换为:

f t1 t2 = zipWith (+) (mapM id [fst, snd] $ t1) (mapM id [fst, snd] $ t2)

67字节

-8个字节感谢ØrjanJohansen。-1个字节感谢Bruce Forte。

如果需要元组输出:

(((,).head<*>last).).((.).flip(.)<*>(zipWith(+).)$mapM id[fst,snd])

在线尝试!

是的,我手动操作不会产生成熟的果实。但我对[a] → (a, a)转换感到满意。

listToPair  [a]  (a, a)
listToPair = (,) . head <*> last
-- listToPair [a, b] = (a, b)

现在,如果有一个函数m (a → b) → a → m b


3
讨厌把它打破给你,但是mapM id[fst,snd]要短一些。
与Orjan约翰森

遗憾的是,您可能正在寻找该功能mapM id高尔夫版本sequence
与Orjan约翰森

对,是真的。我只是在看(<*>)的签名m (a → b) → m a → m b。如此接近…
totallyhuman

1
还有Control.Lens.??,它可能已经被建议列入基地在某些时候。
与Orjan约翰森

我想提取重复的(.mapM id[fst,snd])like let r=(.mapM id[fst,snd]) in r(r.zipWith(+)),但是我无法让typechecker接受无点版本。
xnor

4

54字节

老实说,我怀疑我们会击败@ H.PWiz的44字节解决方案,但是没有人使用(,)实现type class 的事实Functor,因此这是另一个不错的例子:

((<*>snd).((,).).(.fst).(+).fst<*>).flip(fmap.(+).snd)

在线尝试!

说明

类型类的实现Functor2元组是非常相似的的Either(从基4.10.1.0):

instance Functor ((,) a) where
    fmap f (x,y) = (x, f y)

instance Functor (Either a) where
    fmap _ (Left x) = Left x
    fmap f (Right y) = Right (f y)

这对这个挑战意味着什么,就是下面的函数在保留第二个参数的第一个元素的同时添加了第二个元素:

λ f = fmap.(+).snd :: Num a => (a, a) -> (a, a) -> (a, a)
λ f (1,-2) (3,-4)
(3,-6)

因此,如果我们只有一些小帮手,helpPlz = \a b -> (fst a+fst b,snd b)我们就能做(helpPlz<*>).flip(fmap.(+).snd)并且会做。幸运的是,我们拥有为我们提供的工具pointfree

helpPlz = (`ap` snd) . ((,) .) . (. fst) . (+) . fst

因此,只需简单地将该功能插回去,我们便可以得出上述解决方案(请注意,(<*>) = ap这在base中)。


4

60字节

我在uncurry这里没有看到任何爱意,所以我想我会解决这个问题。

uncurry$(uncurry.).flip(.)(flip(.).(+)).(flip(.).((,).).(+))

我以为,所有fstsnd,将参数解包uncurry可能会产生一些结果。显然,它没有我希望的那样富有成果。


2
uncurry太冗长了 :(但是您可以将最外面的括号替换为$
ØrjanJohansen

是的,不幸的是,这是Haskell中很多函数名称的问题。打高尔夫球太久了。但是,感谢您节省了1个字符!
西尔维奥·梅奥洛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.