Haskell函数组成

Fra*_*rth 28 haskell functional-programming function composition

我正在阅读关于Haskell的教程.他们将功能组成定义如下:

(.)                     :: (b->c) -> (a->b) -> (a->c)
f . g                   = \ x -> f (g x)
Run Code Online (Sandbox Code Playgroud)

我没有提供任何例子,我相信这会让我了解这里定义的内容.

有人能提供一个关于如何使用函数组合的简单示例(有解释)吗?

Tom*_*rst 49

函数组合是将两个函数"组合"成一个函数的一种方法.这是一个例子:

假设你有这些功能:

even :: Int -> Bool
not :: Bool -> Bool
Run Code Online (Sandbox Code Playgroud)

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

显而易见的方法如下:

myOdd :: Int -> Bool
myOdd x = not (even x)
Run Code Online (Sandbox Code Playgroud)

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

myOdd :: Int -> Bool
myOdd = not . even
Run Code Online (Sandbox Code Playgroud)

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

这个特别有用的场景是不需要显式的lambda.例如:

map (\x -> not (even x)) [1..9]
Run Code Online (Sandbox Code Playgroud)

可以改写为:

map (not . even) [1..9]
Run Code Online (Sandbox Code Playgroud)

更短,更少的错误空间.

  • @unclerojelio它被称为无点风格.而不是根据给定参数的结果定义`myOdd`("给```,`myOdd`返回与`(not.even)x`"相同的值),它是根据它实际的定义来定义的是("`myOdd`是当`not`由`even`组成时产生的函数). (3认同)

Apo*_*isp 31

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

所有人都是凡人.苏格拉底是个男人.因此,苏格拉底是凡人.

三段论将两个物质含义组合成一个:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal)
Run Code Online (Sandbox Code Playgroud)

因此...

(b -> c) -> (a -> b) -> (a -> c)
Run Code Online (Sandbox Code Playgroud)

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


Dav*_*haw 14

所述组合物fg是第一应用一个函数g到它的参数,然后f通过返回的值g.然后它返回的返回值f.

这种身份可能具有启发性:

f (g x) = (f . g) x
Run Code Online (Sandbox Code Playgroud)

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

int f(int x);
int g(int x);
int theComposition(int x) { return f(g(x)); }
Run Code Online (Sandbox Code Playgroud)


Bri*_*ian 7

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

sqr x = x * x  
inc x = x + 1
Run Code Online (Sandbox Code Playgroud)

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

xSquaredPlusOne = inc . sqr
Run Code Online (Sandbox Code Playgroud)

(意思是

xSquaredPlusOne x = (inc . sqr) x
Run Code Online (Sandbox Code Playgroud)

意思是

xSquaredPlusOne x = inc(sqr x)
Run Code Online (Sandbox Code Playgroud)

因为f = inc和g = sqr).


Chr*_*utz 5

来自关于函数组合的 HaskellWiki 页面:

desort = (reverse . sort)
Run Code Online (Sandbox Code Playgroud)

Nowdesort是一个对列表进行反向排序的函数。基本上,desort将其参数输入到sort,然后将返回值输入sortreverse,然后返回该值。所以它对其进行排序,然后反转排序后的列表。


Mat*_*hid 5

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

cat foo.txt | sort -n | less
Run Code Online (Sandbox Code Playgroud)

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

严格来说,这就像Haskell $运算符一样.你可能会写类似的东西

sum $ sort $ filter (> 0) $ my_list
Run Code Online (Sandbox Code Playgroud)

请注意,与shell示例不同,它从右到左读取.所以我们从my_list输入开始,然后我们filter遍历它,然后我们sort它,然后我们计算sum它.

函数组合运算符.执行类似的操作.上面的例子产生了一个数字 ; 下面的例子产生一个函数:

sum . sort . filter (> 0)
Run Code Online (Sandbox Code Playgroud)

请注意,我们实际上没有将列表输入到此中.相反,我们刚刚创建了一个新函数,我们可以为该函数提供几个不同的列表.例如,您可以命名此函数:

my_function = sum . sort . filter (> 0)
Run Code Online (Sandbox Code Playgroud)

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

map (sum . sort . filter (> 0)) my_lists
Run Code Online (Sandbox Code Playgroud)

您基本上可以在任何可以使用任何其他功能的地方使用它.它只是一种快速且可读的方式来表达"我想将这些功能链接在一起".