Man*_*áoz 33 haskell functional-programming function combinators higher-order-functions
我目前正在做一个函数式编程课程,我对高阶函数和函数作为一等公民的概念感到很开心.但是,我还不能想到许多实用的,概念上令人惊奇的,或者只是简单有趣的高阶函数.(除了典型的和相当乏味map,filter等函数).
你知道这些有趣功能的例子吗?
也许返回函数的函数,返回函数列表的函数(?)等.
我很欣赏Haskell中的例子,这是我目前正在学习的语言:)
Don*_*art 45
好吧,你注意到Haskell没有循环语法?没有while或do或for.因为这些只是高阶函数:
map :: (a -> b) -> [a] -> [b]
foldr :: (a -> b -> b) -> b -> [a] -> b
filter :: (a -> Bool) -> [a] -> [a]
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
iterate :: (a -> a) -> a -> [a]
Run Code Online (Sandbox Code Playgroud)
高阶函数替代了控制结构语言中语法烘焙的需要,这意味着几乎每个Haskell程序都使用这些函数 - 使它们非常有用!
它们是实现良好抽象的第一步,因为我们现在可以将自定义行为插入到通用骨架函数中.
特别是,monad是唯一可能的,因为我们可以链接在一起,并操纵函数来创建程序.
事实是,当它是一阶时,生活很无聊.只有高阶编程才能使编程变得有趣.
sig*_*fpe 37
面向对象编程中使用的许多技术都是缺乏高阶函数的解决方法.
这包括许多在函数式编程中无处不在的设计模式.例如,访问者模式是实现折叠的一种相当复杂的方式.解决方法是使用方法创建一个类,并将类的元素作为参数传入,作为传入函数的替代.
该策略模式是经常通过对象作为参数对于什么是真正目的,功能的替代方案的另一个例子.
类似地,依赖注入通常涉及一些笨重的方案来传递函数的代理,而简单地将函数直接作为参数传递通常会更好.
所以我的答案是,高阶函数通常用于执行OO程序员执行的相同类型的任务,但是直接执行,并且使用很少的样板.
luq*_*qui 15
当我学习一个函数时,我真的开始觉得它的力量可以成为数据结构的一部分.这是一个"消费者monad"(technobabble:免费monad (i ->)).
data Coro i a
= Return a
| Consume (i -> Coro i a)
Run Code Online (Sandbox Code Playgroud)
所以a Coro可以立即产生一个值,或者根据某些输入成为另一个Coro.例如,这是一个Coro Int Int:
Consume $ \x -> Consume $ \y -> Consume $ \z -> Return (x+y+z)
Run Code Online (Sandbox Code Playgroud)
这会消耗三个整数输入并返回它们的总和.您还可以根据输入使其行为不同:
sumStream :: Coro Int Int
sumStream = Consume (go 0)
where
go accum 0 = Return accum
go accum n = Consume (\x -> go (accum+x) (n-1))
Run Code Online (Sandbox Code Playgroud)
这会消耗一个Int,然后在产生它们的总和之前消耗更多的Int.这可以被认为是一个函数,它接受任意多个参数,没有任何语言魔法,只是更高阶函数.
在我开始做Haskell之前,数据结构中的函数是一个非常强大的工具,不属于我的词汇表.
curask还需要高阶函数,Haskell在任何地方都使用它.本质上,一个带两个参数的函数相当于一个函数接受一个参数并返回另一个函数接受一个参数.当你在Haskell中看到这样的类型签名时:
f :: A -> B -> C
Run Code Online (Sandbox Code Playgroud)
... (->)可以读作右关联,表明这实际上是一个返回类型函数的高阶函数B -> C:
f :: A -> (B -> C)
Run Code Online (Sandbox Code Playgroud)
两个参数的非curried函数将改为具有如下类型:
f' :: (A, B) -> C
Run Code Online (Sandbox Code Playgroud)
因此,只要您在Haskell中使用部分应用程序,就可以使用更高阶的函数.
MartínEscardó提供了一个有关高阶函数的有趣例子:
equal :: ((Integer -> Bool) -> Int) -> ((Integer -> Bool) -> Int) -> Bool
Run Code Online (Sandbox Code Playgroud)
给定两个函f, g :: (Integer -> Bool) -> Int,然后equal f g决定是否f和g是(外延上)等于或不,即使f并g没有一个有限区域.实际上,codomain Int可以被具有可判定等式的任何类型替换.
Escardó给出的代码是用Haskell编写的,但是相同的算法应该适用于任何函数式语言.
您可以使用Escardó描述的相同技术来计算任意连续函数的任意精度的定积分.