What are some interesting uses of higher-order functions?

后端 未结 14 571
走了就别回头了
走了就别回头了 2021-01-30 00:55

I\'m currently doing a Functional Programming course and I\'m quite amused by the concept of higher-order functions and functions as first class citizens. However, I can\'t yet

相关标签:
14条回答
  • 2021-01-30 01:42

    Well, you notice that Haskell has no syntax for loops? No while or do or for. Because these are all just higher-order functions:

     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]
    

    Higher-order functions replace the need for baked in syntax in the language for control structures, meaning pretty much every Haskell program uses these functions -- making them quite useful!

    They are the first step towards good abstraction because we can now plug custom behavior into a general purpose skeleton function.

    In particular, monads are only possible because we can chain together, and manipulate functions, to create programs.

    The fact is, life is pretty boring when it is first-order. Programming only gets interesting once you have higher-order.

    0 讨论(0)
  • 2021-01-30 01:44

    I'm a particular fan of higher-order memoization:

    memo :: HasTrie t => (t -> a) -> (t -> a)
    

    (Given any function, return a memoized version of that function. Limited by the fact that the arguments of the function must be able to be encoded into a trie.)

    This is from http://hackage.haskell.org/package/MemoTrie

    0 讨论(0)
  • 2021-01-30 01:48

    It’s been mentioned that Javascript supports certain higher-order functions, including an essay from Joel Spolsky. Mark Jason Dominus wrote an entire book called Higher–Order Perl; the book’s source is available for free download in a variety of fine formats, include PDF.

    Ever since at least Perl 3, Perl has supported functionality more reminiscent of Lisp than of C, but it wasn’t until Perl 5 that full support for closures and all that follows from that was available. And ne of the first Perl 6 implementations was written in Haskell, which has had a lot of influence on how that language’s design has progressed.

    Examples of functional programming approaches in Perl show up in everyday programming, especially with map and grep:

    @ARGV    = map { /\.gz$/ ? "gzip -dc < $_ |" : $_ } @ARGV;
    
    @unempty = grep { defined && length } @many;
    

    Since sort also admits a closure, the map/sort/map pattern is super common:

    @txtfiles = map { $_->[1] }
                sort { 
                        $b->[0]  <=>     $a->[0]
                                  ||
                     lc $a->[1]  cmp  lc $b->[1]
                                  ||
                        $b->[1]  cmp     $a->[1]
                }
                map  { -s => $_ } 
                grep { -f && -T }
                glob("/etc/*");
    

    or

    @sorted_lines = map { $_->[0] }
                    sort {
                         $a->[4] <=> $b->[4] 
                                 ||
                        $a->[-1] cmp $b->[-1]
                                 ||
                         $a->[3] <=> $b->[3]
                                 ||
                         ...
                    }
                    map { [$_ => reverse split /:/] } @lines;
    

    The reduce function makes list hackery easy without looping:

    $sum = reduce { $a + $b } @numbers;
    
    $max = reduce { $a > $b ? $a : $b } $MININT, @numbers;
    

    There’s a lot more than this, but this is just a taste. Closures make it easy to create function generators, writing your own higher-order functions, not just using the builtins. In fact, one of the more common exception models,

    try {
       something();
    } catch {
       oh_drat();
    };
    

    is not a built-in. It is, however, almost trivially defined with try being a function that takes two arguments: a closure in the first arg and a function that takes a closure in the second one.

    Perl 5 doesn’t have have currying built-in, although there is a module for that. Perl 6, though, has currying and first-class continuations built right into it, plus a lot more.

    0 讨论(0)
  • 2021-01-30 01:49

    Higher-order functions are also required for currying, which Haskell uses everywhere. Essentially, a function taking two arguments is equivalent to a function taking one argument and returning another function taking one argument. When you see a type signature like this in Haskell:

    f :: A -> B -> C
    

    ...the (->) can be read as right-associative, showing that this is in fact a higher-order function returning a function of type B -> C:

    f :: A -> (B -> C)
    

    A non-curried function of two arguments would instead have a type like this:

    f' :: (A, B) -> C
    

    So any time you use partial application in Haskell, you're working with higher-order functions.

    0 讨论(0)
  • 2021-01-30 01:50

    Here's a pattern that I haven't seen anyone else mention yet that really surprised me the first time I learned about it. Consider a statistics package where you have a list of samples as your input and you want to calculate a bunch of different statistics on them (there are also plenty of other ways to motivate this). The bottom line is that you have a list of functions that you want to run. How do you run them all?

    statFuncs :: [ [Double] -> Double ]
    statFuncs = [minimum, maximum, mean, median, mode, stddev]
    
    runWith funcs samples = map ($samples) funcs
    

    There's all kinds of higher order goodness going on here, some of which has been mentioned in other answers. But I want to point out the '$' function. When I first saw this use of '$', I was blown away. Before that I hadn't considered it to be very useful other than as a convenient replacement for parentheses...but this was almost magical...

    0 讨论(0)
  • 2021-01-30 01:51

    One thing that's kind of fun, if not particularly practical, is Church Numerals. It's a way of representing integers using nothing but functions. Crazy, I know. <shamelessPlug>Here's an implementation in JavaScript that I made. It might be easier to understand than a Lisp/Haskell implementation. (But probably not, to be honest. JavaScript wasn't really meant for this kind of thing.)</shamelessPlug>

    0 讨论(0)
提交回复
热议问题