4

我是 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)。我不确定是否可以在保持可读性的同时制作此功能的无点版本,但我想确定一下。

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

4

1 回答 1

17

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

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

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

然后可以完全无点:

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

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

1然后可以完全免费foldr (liftM2 (.) (:) (filter . (/=))) [](再次感谢 lambdabot!)但是,我真的不推荐这样做。没有适用于每种情况的无点组合器。

2 (&&&)其实有更一般的类型;它适用于 any Arrow,而不仅仅是(->). 但这在这里无关紧要。

于 2012-04-14T22:08:53.827 回答