2012-04-14 46 views
4

我是一名Haskell初学者,我一直在玩无点功能。我有两个函数的问题 - lambdabot的解决方案是绝对不可读的,并且使代码变得混乱,所以我在这里问,以便有方法来简化函数。使Haskell函数免于点

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

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)。我不确定是否可以在保持可读性的同时制作此函数的免费版本,但我想确保。

任何帮助使这两个功能点免费将不胜感激。

回答

17

那么,func1可以写成fold:func1 = foldr (\x xs -> x : filter (/= x) xs) []。 但是,您不需要,因为它与标准功能nub完全相同。

而且你可以从func2使用(&&&) :: (a -> b) -> (a -> c) -> a -> (b,c) 组合子从Control.Arrow删除一些要点:

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

,然后可以进行充分点免费电话:

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

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

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

(&&&)实际上具有更一般的类型;它适用于任何Arrow,而不仅仅是(->)。但这在这里没有关系。