【问题标题】:Looking for an explanation of function compositionHaskell 函数组合
【发布时间】:2010-12-01 08:17:57
【问题描述】:

我正在阅读有关 Haskell 的 this 教程。他们将函数组合定义如下:

(.)                     :: (b->c) -> (a->b) -> (a->c)
f . g                   = \ x -> f (g x)

没有提供任何示例,我相信这会启发我了解此处定义的内容。

谁能提供一个如何使用函数组合的简单示例(附说明)?

【问题讨论】:

    标签: function haskell functional-programming composition


    【解决方案1】:

    有趣的旁注。函数组合相当于逻辑中的三段论:

    所有的人都会死。苏格拉底是个男人。因此,苏格拉底是必死的。

    三段论将两种实质含义合二为一:

    (Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal)
    

    所以……

    (b -> c) -> (a -> b) -> (a -> c)
    

    ...这是.函数的类型。

    【讨论】:

      【解决方案2】:

      函数组合是一种将两个或多个函数链接在一起的方法。它通常被比作贝壳管道。例如,在 Unix 风格的 shell 中,你可能会写类似

      cat foo.txt | sort -n | less
      

      这运行cat,将其输出提供给sort,并将其输出提供给less

      严格来说,这就像 Haskell 的 $ 运算符。你可能会写类似

      sum $ sort $ filter (> 0) $ my_list
      

      请注意,与 shell 示例不同,它是从右向左读取的。所以我们从my_list作为输入开始,然后我们在它上面运行filter,然后我们sort它,然后我们计算它的sum

      函数组合运算符. 做了类似的事情。上面的例子产生了一个数字;下面的例子产生了一个函数

      sum . sort . filter (> 0)
      

      请注意,我们实际上并未将列表输入其中。相反,我们刚刚创建了一个新函数,我们可以向该函数提供几个不同的列表。例如,您可以将这个函数命名为:

      my_function = sum . sort . filter (> 0)
      

      或者你可以将它作为参数传递给另一个函数:

      map (sum . sort . filter (> 0)) my_lists
      

      您基本上可以在任何可以使用任何其他功能的地方使用它。这只是表达“我想将这些函数链接在一起”的一种快速易读的方式。

      【讨论】:

        【解决方案3】:

        函数组合是一种将两个函数“组合”成一个函数的方法。这是一个例子:

        假设你有这些功能:

        even :: Int -> Bool
        not :: Bool -> Bool
        

        并且您想使用上述两个定义自己的myOdd :: Int -> Bool 函数。

        执行此操作的明显方法如下:

        myOdd :: Int -> Bool
        myOdd x = not (even x)
        

        但这可以使用函数组合更简洁地完成:

        myOdd :: Int -> Bool
        myOdd = not . even
        

        myOdd 函数的行为完全相同,但第二个函数是通过将两个函数“粘合”在一起而创建的。

        一个特别有用的场景是消除对显式 lambda 的需求。例如:

        map (\x -> not (even x)) [1..9]
        

        可以改写为:

        map (not . even) [1..9]
        

        短一点,出错的空间更小。

        【讨论】:

        • 定义里怎么不用显示入参?例如。你怎么不写myOdd x = not . even x
        • @unclerojelio 这就是所谓的无点风格。不是根据给定参数的结果定义myOdd(“给定xmyOdd返回与(not . even) x相同的值”),而是根据它的实际情况来定义(“@987654333 @ 是 noteven") 组合时产生的函数。
        【解决方案4】:

        这个例子是人为的,但假设我们有

        sqr x = x * x  
        inc x = x + 1
        

        我们想写一个计算 x^2+1 的函数。我们可以写

        xSquaredPlusOne = inc . sqr
        

        (意思是

        xSquaredPlusOne x = (inc . sqr) x
        

        意思是

        xSquaredPlusOne x = inc(sqr x)
        

        因为 f=inc 和 g=sqr)。

        【讨论】:

          【解决方案5】:

          来自HaskellWiki page on function composition:

          desort = (reverse . sort)
          

          现在desort 是一个反向排序列表的函数。基本上,desort 将它的参数提供给sort,然后将来自sort 的返回值提供给reverse,然后返回。所以它对它进行排序,然后它反转排序的列表。

          【讨论】:

            【解决方案6】:

            fg组合 是一个函数,它首先将g 应用于其参数,然后将f 应用于g 返回的值。然后返回f的返回值。

            这个身份可能很有启发性:

            f (g x) = (f . g) x

            如果您有 Java/C 背景,请考虑以下示例:

            int f(int x);
            int g(int x);
            int theComposition(int x) { return f(g(x)); }
            

            【讨论】:

              猜你喜欢
              • 2016-04-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-12-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多