【发布时间】:2020-06-16 07:56:06
【问题描述】:
我一直想知道如何无点实现不同的标准 Haskell 函数。目前,我对uncurry 很感兴趣,我觉得这个很重要。
主要问题是我们无法(或在我看来)对论点进行分组。如果我们使用uncurry(实际上,uncurry ($) 就足够了),那么解决方案将非常简单:
- 创建一个元组
(f, (x, y))。 - 将
assoc1 :: (a, (b, c)) -> ((a, b), c)应用于元组并获得((f, x), y)。 - 将未咖喱化的
($)应用于该对的第一个元素并得到(f x, y)。 - 将未咖喱化的
($)应用于该对本身并得到f x y。
如果没有未经处理的($),我们将不得不分别提取这对的两个元素。例如:
uncurry f pair = f (fst pair) (snd pair)
我不认为这是实现无点的顺利方法。
事实上,我们已经按照我们的要求得到了这个未经处理的($):Control.Arrow.apply(其他对解决方案组合器有用的也可以从Control.Arrow 导入)。因此:
import Control.Arrow ((>>>), (&&&), first, app)
myUncurry = let myAssoc1 = (fst &&& (fst . snd)) &&& (snd . snd)
in (,) >>> (>>> myAssoc1 >>> first app >>> app)
然而,这感觉有点像作弊。
有没有其他方法可以解决这个问题,不需要像app 这样的东西?
【问题讨论】:
-
我目前看不到任何更简单的解决方案。此外,“无积分”游戏的规则有些模糊,因为它取决于允许使用哪些库原语。当我编写无点代码时,我倾向于使用
curry和uncurry作为原语。 -
我认为有一个很好的原因
uncurry通常包括在内。我们使事情变得毫无意义,将它们带入了profunctors的土地。curry和uncurry在这种情况下是非常简单的适配器。 -
你可以用
(<*>)和const来做所有事情(偶尔fix用于类型检查)(当然还有你正在使用的任何数据类型的构造函数/消除器)。从技术上讲,您甚至不需要(.)。结果通常不是很漂亮,所以像uncurry这样的附加组合基本上是为了美化。 -
@ZhiltsoffIgor
(<*>)和const是S和K中的 SKI combinators,已知它们是图灵完备的。因此,您可以以任何可以想象的方式将功能与它们组合在一起,这是有道理的。正如 luqui 所说(这里是fst、snd和(,)),您确实需要针对您正在使用的类型的构造函数和消除器,但是您可以使用 SKI 以任何您喜欢的方式来玩弄它们。 -
同一个底层结构有各种不同的表达方式:
uncurry f pair = f (fst pair) (snd pair)=uncurry f = f <$> fst <*> snd=uncurry f = liftA2 f fst snd=uncurry = (<*> snd) . (<$> fst)=uncurry = flip (flip liftA2 fst) snd= ...
标签: haskell tuples currying arrows pointfree