使Haskell功能无点

时间:2012-04-14 22:01:09

标签: haskell pointfree

我是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 个答案:

答案 0 :(得分:17)

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

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

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

然后可以使其完全无点:

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

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

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

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