Function Haskell函数组合
我正在读哈斯克尔的教程。它们将功能组合定义为以下内容:Function Haskell函数组合,function,haskell,functional-programming,composition,Function,Haskell,Functional Programming,Composition,我正在读哈斯克尔的教程。它们将功能组合定义为以下内容: (.) :: (b->c) -> (a->b) -> (a->c) f . g = \ x -> f (g x) myOdd :: Int -> Bool myOdd x = not (even x) 没有提供任何例子,我相信这些例子会启发我这里的定义 有人能提供一个简单的例子(带解释)说明函数组合是如何使用的吗?f和g
(.) :: (b->c) -> (a->b) -> (a->c)
f . g = \ x -> f (g x)
myOdd :: Int -> Bool
myOdd x = not (even x)
没有提供任何例子,我相信这些例子会启发我这里的定义
有人能提供一个简单的例子(带解释)说明函数组合是如何使用的吗?f和g
的组合是一个函数,它首先将g
应用于它的参数,然后将f
应用于g
返回的值。然后返回f
的返回值
这一身份可能具有启发性:
f (g x) = (f . g) x
如果你有爪哇/C背景,请考虑这个例子:
int f(int x);
int g(int x);
int theComposition(int x) { return f(g(x)); }
从
现在,
解吸
是一个对列表进行反向排序的函数。基本上,解吸
将它的参数输入到排序
,然后将排序
的返回值输入到反向
,返回该值。所以它对它进行排序,然后将排序后的列表反转。这个例子是人为的,但假设我们有
sqr x = x * x
inc x = x + 1
我们想写一个计算x^2+1的函数。我们可以写作
xSquaredPlusOne = inc . sqr
(这意味着
xSquaredPlusOne x = (inc . sqr) x
xSquaredPlusOne x = inc(sqr x)
也就是说
xSquaredPlusOne x = (inc . sqr) x
xSquaredPlusOne x = inc(sqr x)
因为f=inc和g=sqr) 函数组合是将两个函数“组合”为一个函数的方法。下面是一个例子: 假设您具有以下功能:
even :: Int -> Bool
not :: Bool -> Bool
您需要使用上述两个函数定义自己的myOdd::Int->Bool
函数
显而易见的方法是:
(.) :: (b->c) -> (a->b) -> (a->c)
f . g = \ x -> f (g x)
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]
稍微短一点,减少出错的空间。有趣的旁注。函数组合相当于逻辑中的三段论: 所有的人都是凡人。苏格拉底是个男人。因此,苏格拉底是凡人 三段论将两个重要含义合为一:
(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal)
因此
(b -> c) -> (a -> b) -> (a -> c)
。。。这是
函数的类型。函数组合是将两个或多个函数链接在一起的一种方法。它经常被比作壳牌管道。例如,在Unix样式的shell中,您可以编写如下内容
cat foo.txt | sort -n | less
sum $ sort $ filter (> 0) $ my_list
这将运行cat
,将其输出馈送到sort
,并将其输出馈送到less
严格来说,这类似于Haskell$
操作符。你可能会写这样的东西
cat foo.txt | sort -n | less
sum $ sort $ filter (> 0) $ my_list
请注意,与shell示例不同,它从右向左读取。因此,我们首先以my_list
作为输入,然后对其运行filter
,然后对其进行sort
排序,然后计算其sum
函数组合运算符
,执行类似的操作。上面的例子产生了一个数字;下面的示例生成一个函数:
my_function = sum . sort . filter (> 0)
map (sum . sort . filter (> 0)) my_lists
请注意,我们实际上并没有将列表输入到这个列表中。相反,我们刚刚创建了一个新函数,可以向该函数提供几个不同的列表。例如,您可以将此函数命名为:
my_function = sum . sort . filter (> 0)
map (sum . sort . filter (> 0)) my_lists
或者您可以将其作为参数传递给另一个函数:
my_function = sum . sort . filter (> 0)
map (sum . sort . filter (> 0)) my_lists
你基本上可以在任何地方使用它,你可以使用任何其他类型的函数。这只是一种快速易读的方式,表示“我想将这些函数链接在一起”。为什么不需要在定义中显示输入参数?例如。你为什么不写
myodx=not。即使是x,它也被称为无点风格。与其根据给定参数的结果定义myOdd
(“给定x
,myOdd
返回与(not.event)x
)相同的值,myOdd
是根据实际情况定义的(myOdd
是当not
由偶数
组成时产生的函数)。