重写一个未经证实的函数haskell

时间:2013-10-24 00:58:41

标签: function haskell tuples

我一直在学习如何解决并在haskell中应用$函数,但我仍然遇到将未经处理的函数转换为不那么神秘的函数的问题。

我给出的功能是

apple = map $ uncurry $ flip ($)

我意识到这需要一个元组列表并将元组中的相应函数应用于变量里面。所以我试图将其重写为

apple ls = foldr function _ ls
    where function (a,b) c = (uncurry b) (a,c)

我得到_的错误作为解析错误,我不知道使用哪个起点。我需要制作这种多态,我意识到这很可能不会让它变得不那么神秘。有任何想法吗?他们将非常感激

2 个答案:

答案 0 :(得分:7)

Apple有类型

apple :: [(a, a->b)] -> [b]

我们可以将其重写为

apple ls = map (\(a, f) -> f a) ls

所以用foldr写这个是非常可行的,

apple ls = foldr (\(a, f) rest -> f a : rest) [] ls

或者,我们可以将其重写为pointfree

apple = foldr ( (:) . (uncurry . flip $ ($)) ) []

解析错误的原因是_是“我不关心的变量”的特殊语法。这让你写下像

这样的东西
 foo _ _ _ _ a = a

并没有得到重复变量的错误。基本上,我们只使用起始空列表填充_并修复function,以便将其附加到c,而不是尝试将其应用于a

如果我想以最清晰的方式写这个,那就是原来的

apple = map . uncurry . flip $ ($)

非常好。

答案 1 :(得分:1)

理解的关键是消除复杂性。

因此我建议你先处理一个元组。写下以下函数:

 tapp :: (a, a ->b) -> b

就($)和flip以及uncurry而言。 (为了使它更容易,您可以先为元组(a -> b, a)首先执行此操作。)

接下来,向自己说明地图的工作原理:如果您有一个功能f :: (a -> b),那么map f将是一个功能[a] -> [b]。因此,map tapp可以满足您的需求。

现在,您可以根据其定义替换tapp中的map (tapp)(这是引用透明度的好处)。 这应该会让你回到原来的表达。或多或少,因为,例如:

f $ g h

可以写

f (g h)

(f . g) h