使 Haskell 函数无点

Posted

技术标签:

【中文标题】使 Haskell 函数无点【英文标题】:Making Haskell functions point-free 【发布时间】:2012-04-14 22:01:09 【问题描述】:

我是一名 Haskell 初学者,我一直在玩弄无点函数。我有两个函数的问题 - lambdabot 的解决方案绝对不可读并且使代码混淆,所以我在这里询问是否有办法简化函数。

第一个函数从列表中删除重复项。

func1 :: Eq a => [a] -> [a]
func1 [] = []
func1 (x:xs) = x : (func1 . filter (/=x) $ xs)

我尝试使用foldr>>= 制作此函数的无点版本,但没有成功。

第二个函数将列表映射到包含原始元素的元组列表以及它们在列表中出现的频率。

func2 :: Eq a => [a] -> [(a, Int)]
func2 xs = map ( \f -> (f, count f xs) ) xs

在哪里count a = length.filter(==a)。我不确定是否可以在保持可读性的同时制作此函数的无点版本,但我想确定一下。

任何有关使这两个功能无点的帮助将不胜感激。

【问题讨论】:

【参考方案1】:

好吧,func1 可以写成折叠:func1 = foldr (\x xs -> x : filter (/= x) xs) []1 但是,您不必这样做,因为它与标准函数 nub 相同。

您可以使用来自Control.Arrow(&&&) :: (a -> b) -> (a -> c) -> a -> (b,c)2 组合器从func2 中删除一些点:

func2 xs = map (id &&& (`count` xs)) xs

然后可以完全无点:

func2 = (id &&&) . flip count >>= map

但是,坦率地说,我不得不使用 lambdabot 来完成最后一步;我建议保持该功能的原始形式。无点风格只有在有助于理解时才有用;如果您在使函数无点时遇到困难,那么它可能会适得其反。

1 然后可以将其作为foldr (liftM2 (.) (:) (filter . (/=))) [] 完全免费(再次感谢 lambdabot!)但是,我真的不建议这样做。 每个情况都没有一个无点组合器。

2(&&&)其实有一个更通用的类型;它适用于任何Arrow,而不仅仅是(->)。但这与这里无关。

【讨论】:

以上是关于使 Haskell 函数无点的主要内容,如果未能解决你的问题,请参考以下文章

哪种 KeyBoard / KeyBoard Layout 最适合 Haskell 编程? haskell 是不是将所有数学符号作为函数?

Haskell“字符串移动”函数

Haskell入门篇六:匿名函数定义

如何优化这个 Haskell 程序?

Haskell代码编程

Haskell缩进不会排列函数参数