More Functional Patterns: Higher-order functions and guards

Continuing our foray into the More Functional Patterns chapter, today we're looking at higher-order functions and guards.

# Higher-order functions

First off, let's establish some common ground and agree on the definition. According to Wikipedia and the Haskell wiki, a higher-order function is a function that takes other functions as arguments or returns a function as a result. In essence, it's a function that operates on functions as values. Because functions are just any other value in haskell1, this comes very naturally to the language.

So to qualify as a higher-order function, a function must fulfill one of two criteria:

Accept a function as a parameter

`map` and sorting functions are great examples of this. For instance, `map`'s signature is `map :: (a -> b) -> [a] -> [b]`, where the first parameter is the function used to transform the values of type `a` in the list to values of type `b`. Sorting functions could take a comparison function (`a -> a -> Ordering`) and a list (`[a]`), sort the list for you and return the sorted list.

Return a function

This probably happens more than you realize. Any function that accepts more than one argument in Haskell is by default a higher-order function due to how the lambda calculus works. That said, you can also explicitly return a partially applied function based on the input arguments. For instance, this example takes a boolean value saying whether the function should return a partially applied multiplication or addition, and the first argument to apply to the calculation. It returns the partially applied function:

``````       f :: Num a => Bool -> a -> (a -> a)
f multiply n =
if multiply then
(n*)
else
(n+)``````

It's a silly example, but it gets the point across.

# Guards

Next up, the book returns to a form of pattern matching by introducing guards, which allow us to run code conditionally based on the truth of a statement. If you think that sounds a lot like an `if-then-else` expression, that's because it works pretty much the same but with some different syntax. We'll run through a couple of different examples to examine the various features that are introduced.

The basic syntax looks like this:

``````    myAbs :: Integer -> Integer
myAbs x
| x < 0     = (-x)
| otherwise =   x``````

This function has two guards, each beginning with a pipe symbol (`|`). Note that we don't need an equals sign after the arguments in the first line of the definition; instead, the symbol comes after each respective guard. The first of the guards that evaluates to `True` will be executed.

In this function, we have two cases: One for when the value of `x` is negative (in which case we'll return the absolute value of `x`), and one for every other case. In the above example, we have used the word `otherwise`, which is a synonym for `True`, as a catch-all for every other case.

If we want to explicitly enumerate all options, we can do that too:

``````    myAbs :: Integer -> Integer
myAbs x
| x <  0 = (-x)
| x >= 0 =   x``````

This will work the exact same as the previous version, but in this case we're handling all cases explicitly. When explicitly listing all options, make sure you have enabled warnings (or errors) for non-exhaustive patterns to avoid accidentally partial functions.

What if we want to share some values between the different guards? We can use `where`-statements for that! Imagine a function that takes the lengths of the two legs (catheti) of a right triangle and returns whether the triangle is big, small, or medium based on the length of the hypotenuse:

``````    triangleSize :: (Floating a, Ord a) => a -> a -> String
triangleSize c1 c2
| h >= 5 = "Big triangle"
| h >= 2 = "Medium triangle"
| h <  2 = "Small triangle"
where h = sqrt (c1^2 + c2^2)``````

When declaring variables like this, they're in scope for all of the guards.

This last example also demonstrates the importance of order on the guards. Because only the first guard that evaluates to `True` is executed, the above function works as expected. If we switched the two guards for big and medium triangles, no triangle would ever be considered 'big'. What a sad world that would be.

# Next up

That was all we had time for today, my dear reader. We still have a little bit left of this chapter: function composition and pointfree style. Two very interesting topics which I'm looking forward to covering next time. Until then: take care!

# Footnotes

1You may have heard the term 'first-class functions'. This is what that means. You can pass functions around like any other variable, store them in data structures, assign them to variables, and so forth. See MDN or Wikipedia for more.

More Functional Patterns: Pattern Matching

Woah, I have to move the text now too?

We've reached chapter 7: More Functional Patterns. This is a pretty big chapter that covers a lot of ground, so to make it more digestible to you (and more manageable to me), I'm going to break this chapter up into multiple pieces. In this post, we'll be looking at pattern matching and case expressions. Later posts will cover higher-order functions, function composition, and pointfree style, so there's lots to look forward to!

# Pattern matching

"Pattern matching is an integral and ubiquitous feature of Haskell". Thus opens the sub-chapter on pattern matching. If you've seen any amount of Haskell code, you've probably come across it, but in case you haven't (and if you have: just to make sure we're on the same page), here's a primer.

Pattern matching is a way for us to match values against certain 'patterns'. Depending on the context, a pattern can be a wide range of things, including specific strings, numeric literals and list syntax; pattern matching can match on any and all data constructors. Pattern matching can even let us match on the inner structure of the thing we're matching on, such as a list or a tuple. Let's have some examples.

We can check whether a provided `Integer` is of a specific value, like in the following case:

``````      isTheAnswer :: Integer -> Bool

We can check whether a list contains zero, one, or many elements:

``````        listState :: [a] -> String
listState [] = "The list is empty"
listState [_] = "The list has one element"
listState (_:_:_) = "The list has at least two elements"``````

We can also check which data constructor has been used to create a value and extract the constructor parameters from it or even check them for specific values:

``````        data User = LoggedIn String | Anonymous

userInfo :: User -> String
userInfo Anonymous = "The user is anonymous"

This covers some of the patterns you might see used with pattern matching. Keep in mind that the order of the patterns matter: they are evaluated from top to bottom, and once a pattern matches, no more cases will get checked.

## Covering all the cases

When pattern matching, you should always handle all cases to avoid partial functions. This might seem like a hassle, but you don't need to handle all the cases explicitly. As seen in the first example (`isTheAnswer`), the `_` pattern works as a catch-all, meaning that if no other patterns have matched yet, this will match anything.

In addition to just being vigilant about matching all possible combinations, you can also turn up the compiler's crankiness by using the `-Wall` flag. This will give you warnings if your patterns are non-exhaustive.

# Case expressions (or: more pattern matching)

Similarly to the pattern matching above, we also have `case` expressions in Haskell. They work the same way as basic pattern matching, but the syntax is a bit different. In short, it gives you all the power that you get from pattern matching, but with a bit more syntax. Let's rewrite the `listState` function above using a case expression to see the similarities:

``````    listState :: [a] -> String
listState xs =
case xs of
[] -> "The list is empty"
[_] -> "The list has one element"
(_:_:_) -> "The list has at least two elements"``````

This looks very much like pattern matching (and serves the same purpose in this case), except that we use the `case ... of` structure to match on a named variable instead of directly on an input. Which is more appropriate depends on your use case and preferences.

And that's it for today, kids. A shorter, more digestible format that covers only the most essential. I'll cover the rest of the chapter in this way, and then we'll see what works best moving forward. Next time: higher-order functions! Until then: take care!

# Async Rust: async main

Improving async ergonomics

New and improved.

In the previous post we had an introductory glance at `async/.await` in Rust, looking at what it does and how you'd use it. However, the little bit of code we were left with at the end still felt a bit rough. Coming from languages where you can have an async `main` function (or at least one that lets you act as if it is), it felt like an extra hurdle to have to extract all async functionality out into a separate function.

Luckily, Reddit user mbuesing pointed out that there is an attribute available in async-std that you can use to make your `main` function asynchronous: `async_std::main`! Let's have a look at what changes we'd have to make to incorporate that.

First off, let's update the `Cargo.toml` file. It's mostly the same as last time, but we're going to have to add the "attributes" feature from async-std:

``````  [package]
name = "async-basics"
version = "0.1.0"
edition = "2018"

[dependencies]
async-std = { version = "1", features = ["attributes"] }
surf = "1"``````

Next up, let's update the `main.rs` file. If we're doing everything within the `main` function, we can cut it down to about 8 lines of code, compared to the 14 lines we had last time, and because it's such a simple program, it's not any less readable:

``````  use surf;

#[async_std::main]
async fn main() {
match surf::get("https://pokeapi.co/api/v2/move/surf").recv_string().await {
Ok(s) => println!("Fetched results: {:#?}", s),
Err(e) => println!("Got an error: {:?}", e),
};
}``````

So there you have it. With some extra attributes, we can make async code pretty ergonomic in Rust. Now, let's make something cool!