【问题标题】:Making Haskell functions point-free使 Haskell 函数无点
【发布时间】: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)。我不确定是否可以在保持可读性的同时制作此函数的无点版本,但我想确定一下。

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

【问题讨论】:

    标签: haskell pointfree


    【解决方案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,而不仅仅是(->)。但这与这里无关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多