Functions

Posted on 2018-01-30 by nbloomf
Tags: arithmetic-made-difficult, literate-haskell

This page is part of a series on Arithmetic Made Difficult.

This post is literate Haskell; you can load the source into GHCi and play along.


{-# LANGUAGE NoImplicitPrelude #-}
module Functions (
  id, compose, const, apply, _test_functions, main_functions
) where

import Testing

Today we’ll nail down some generic functions.

Every set has an associated identity function.

Let \(A\) be a set. We define \(\id : A \rightarrow A\) by \(\id(x) = x\).

In Haskell:

Given two functions, one with domain \(B\) and the other with codomain \(B\), we can construct their composite.

Let \(A\), \(B\), and \(C\) be sets. Given \(f : A \rightarrow B\) and \(B : B \rightarrow C\), we define \(\compose(g)(f) : A \rightarrow C\) by \[\compose(g)(f)(x) = g(f(x)).\]

In Haskell:

\(\id\) is neutral under \(\compose(\ast)(\ast)\).

Let \(A\) and \(B\) be sets, with \(f : A \rightarrow B\). Then we have the following.

  1. \(\compose(\id)(f) = f\).
  2. \(\compose(f)(\id) = f\).
  1. Let \(a \in A\). Then we have \[\begin{eqnarray*} & & \compose(\id)(f)(a) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & \id(f(a)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-id} = & f(a) \end{eqnarray*}\] as needed.
  2. Let \(a \in A\). Then we have \[\begin{eqnarray*} & & \compose(f)(\id)(a) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & f(\id(a)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-id} = & f(a) \end{eqnarray*}\] as needed.

\(\compose(\ast)(\ast)\) is associative.

Let \(A\), \(B\), \(C\), and \(D\) be sets. For all \(f : A \rightarrow B\), \(g : B \rightarrow C\), and \(h : C \rightarrow D\), we have \[\compose(h)(\compose(g)(f)) = \compose(\compose(h)(g))(f).\]

Let \(a \in A\). Then we have \[\begin{eqnarray*} & & \compose(h)(\compose(g)(f))(a) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & h(\compose(g)(f)(a)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & h(g(f(a))) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & \compose(h)(g)(f(a)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & \compose(\compose(h)(g))(f)(a) \end{eqnarray*}\] as needed.

The \(\const\) function throws away its second argument.

Let \(A\) and \(B\) be sets. We define \(\const : B \rightarrow B^A\) by \[\const(b)(a) = b.\]

In Haskell:

\(\const(b)\) absorbs under \(\compose(\ast)(\ast)\) from the left.

Let \(A\), \(B\), and \(C\) be sets. For all \(f : A \rightarrow B\) and \(c \in C\) we have \[\compose(\const(c))(f) = \const(c).\]

Let \(a \in A\). Note that \[\begin{eqnarray*} & & \compose(\const(c))(f)(a) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & \const(c)(f(a)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-const} = & c \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-const} = & \const(c)(a) \end{eqnarray*}\] as needed.

\(\apply\) is operatorized function application.

Given \(f : A \rightarrow B\) and \(x \in A\), we define \[\apply(f)(x) = f(x).\]

In Haskell:

\(\apply\) distributes over compose.

If \(f : A \rightarrow B\) and \(g : B \rightarrow C\) we have \[\apply(\compose(g)(f)) = \compose(\apply(g))(\apply(f)).\]

Let \(x \in A\). Now we have \[\begin{eqnarray*} & & \apply(\compose(g)(f))(x) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-apply} = & \compose(g)(f)(x) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & g(f(x)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-apply} = & \apply(g)(f(x)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-apply} = & \apply(g)(\apply(f)(x)) \\ & \href{/posts/arithmetic-made-difficult/Functions.html#def-compose} = & \compose(\apply(g))(\apply(f))(x) \end{eqnarray*}\] as needed.

Testing

Suite:

_test_functions ::
  ( Equal a, Show a, Arbitrary a, CoArbitrary a, TypeName a
  , Equal b, Show b, Arbitrary b, CoArbitrary b, TypeName b
  , Equal c, Show c, Arbitrary c, CoArbitrary c, TypeName c
  , Equal d, Show d, Arbitrary d, CoArbitrary d, TypeName d
  ) => Int -> Int -> a -> b -> c -> d -> IO ()
_test_functions size cases a b c d = do
  testLabel0 "Functions"
  let args = testArgs size cases

  runTest args (_test_compose_id_left a b)
  runTest args (_test_compose_id_right a b)
  runTest args (_test_compose_associative a b c d)
  runTest args (_test_compose_const_left a b c)
  runTest args (_test_apply_compose_distribute a b c)

Main:

main_functions :: IO ()
main_functions = do
  _test_functions 1 1 () () () ()