Showing posts with label functional programming. Show all posts
Showing posts with label functional programming. Show all posts

02 February 2019

Pattern Matching Wildcard Commentary

While reading Google's Haskell training, I encountered some code for the function (&&), which I thought was mildly unintuitive:

(&&) :: Bool -> Bool -> Bool
True && y = y
_ && _ = False

The reason I found this definition odd is that the author chose to use a wildcard (the first underscore in the second line) instead of the explicit data False. Since Bool only has two choices, True and False, I think explicitly using False instead is more intuitive, since I had to think about the other values that the wildcard can take on besides False. Furthermore, the Haskell compiler, ghc, will validate whether all patterns are matched in the function definition.

Thus, I would rewrite the function as:

True && y = y
False && _ = False

*

Additional commentary:

Brian Hamrick likes when the wildcard is conceptually a catch-all, i.e.:

True && True = True
_ && _ = False

At first, I thought this best describes the logical truth table, where the only True result is from the inputs (True, True). However, this changes the laziness properties of the function in Haskell: the second argument is forced to evaluate when the first one is True since we do not have enough information to match (AN: this was not obvious to me at first). If the second argument is True, then we match the first line; otherwise, we match the second line, so the second argument gets reduced to weak head normal form (WHNF).

*

Thanks to Brian Hamrick for help with this expository post.

05 June 2012

C++ Don'ts, Part I

Hello! Today we will be talking about things not to do in C++! Today's topic will be linked lists, more specifically integer linked lists.

We can define a non-null node as follows:

template<int I_, typename T_>
struct Node {
    static const int value = I_;
    static const int size = 1 + Next::size;
    typedef T_ Next;
};

and the null node as follows:

struct End {
    static const int size = 0;
};

We then can implement getting the size of a linked list:

template<typename L_>
struct Size {
    static const int value = L_::size;
};

where L_ is either a Node or an End.

Recursive prints can be done as follows using specialization:

template<typename L_>
struct Print;


template<int I_, typename T_>
struct Print<Node<I_, T_> > {
    static void print() {
        std::cout << I_ << "\n";
        Print<T_>::print();
    }
};


template<>
struct Print {
    static void print() {}
};

See where this is going? Now go implement map, filter, and reduce. :)