以 pointfree 风格编写函数的一般方案是什么?

2023-11-24

我正在通过20 个中级 Haskell 练习目前,这是一个非常有趣的练习。它涉及实现类型类的各种实例Functor and Monad(以及需要的函数Functors and Monads 作为参数)但是有可爱的名字,比如Furry and Misty掩饰我们正在做的事情(产生一些有趣的代码)。

我一直在尝试以无点风格来做其中的一些事情,我想知道是否有一个通用方案可以将有点(?)定义转变为无点定义。例如,这里是类型类Misty:

class Misty m where
  unicorn :: a -> m a
  banana :: (a -> m b) -> m a -> m b

(功能unicorn and banana are return and >>=,以防不明显)这是我的实现apple(相当于flip ap):

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple x f = banana (\g -> banana (unicorn . g) x) f

练习的后面部分让您实现以下版本liftM, liftM2等等。这是我的解决方案:

appleTurnover :: (Misty m) => m (a -> b) -> m a -> m b
appleTurnover = flip apple

banana1 :: (Misty m) => (a -> b) -> m a -> m b
banana1 =  appleTurnover . unicorn

banana2 :: (Misty m) => (a -> b -> c) -> m a -> m b -> m c
banana2 f = appleTurnover . banana1 f

banana3 :: (Misty m) => (a -> b -> c -> d) -> m a -> m b -> m c -> m d
banana3 f x = appleTurnover . banana2 f x

banana4 :: (Misty m) => (a -> b -> c -> d -> e) -> m a -> m b -> m c -> m d -> m e
banana4 f x y = appleTurnover . banana3 f x y

Now, banana1(相当于liftM or fmap)我能够通过一个合适的定义以 pointfree 风格实现appleTurnover。但对于其他三个函数,我必须使用参数。

我的问题是:有没有办法将这样的定义转变为无点定义?


正如所证明的pointfree实用程序,可以自动执行任何此类转换。然而,结果往往是混乱的而不是改进的。如果一个人的目标是增强易读性而不是破坏它,那么第一个目标应该是识别why表达式具有特定的结构,找到合适的抽象,并以这种方式构建事物。

最简单的结构是将事物简单地链接在线性管道中,这是简单的函数组合。这本身就让我们走得很远,但正如你所注意到的,它并不能处理所有事情。

一种概括是带有附加参数的函数,这些参数可以逐步构建。这是一个例子:定义onResult = (. (.))。现在,申请onResultn 次到初始值id为您提供具有 n 元函数结果的函数组合。所以我们可以定义comp2 = onResult (.),然后写comp2 not (&&)定义 NAND 操作。

另一个概括(实际上包含上述内容)是定义将函数应用于较大值的组件的运算符。这里的一个例子是first and second in Control.Arrow,适用于 2 元组。康纳尔埃利奥特语义编辑器组合器都是基于这种方法。

稍微不同的情况是当您在某种类型上有多参数函数时b,和一个函数a -> b,并且需要使用将它们组合成一个多参数函数a。对于二元函数的常见情况,该模块Data.Function提供了on组合器,您可以使用它来编写表达式,例如compare `on` fst比较 2 元组的第一个元素。

当单个参数被多次使用时,这是一个更棘手的问题,但这里也可以提取有意义的重复模式。这里的常见情况是将多个函数应用于单个参数,然后使用另一个函数收集结果。这恰好对应于Applicative函数的实例,它让我们可以编写如下表达式(&&) <$> (> 3) <*> (< 9)检查一个数字是否落在给定范围内。

重要的是,如果您想在实际代码中使用其中任何一个,请考虑表达式的含义means以及它如何反映在结构中。如果您这样做,然后使用有意义的组合器将其重构为 pointfree 样式,您通常会实现代码的意图clearer与其他情况不同,与典型的输出不同pointfree.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以 pointfree 风格编写函数的一般方案是什么? 的相关文章

随机推荐