         )
     }
 
+    /// Modifies the info loader state for a page completion event.
+    ///
+    /// - parameter transform: The info loader state transform.
+    /// - parameter pageEvent: A function to create a page event, given the current and previous loader states.
+    private func modifyStateForPageCompletion(transform transform: InfoLoaderStateTransform,
+                                              pageEvent: LoaderEventForStates)
+    {
+        var newState: InfoLoaderState<Element, Info, Error>?
+
+        let previousState = infoState.modify({ current in
+            newState = transform(current)
+            return newState!
+        })
+
+        eventsPipe.1.sendNext(pageEvent(newState!.loaderState, previousState.loaderState))
+    }
+
+    /// Completes the loading of a page.
+    ///
+    /// - parameter result:                      The result of loading the page.
+    /// - parameter combine:                     A function to combine the current and newly loaded elements.
+    /// - parameter loaderEventForLoaded:          A function to create a page event for a successfully loaded page.
+    /// - parameter loaderEventForFailed:          A function to create a page event for a failed page load.
+    /// - parameter nextPageStateForSuccess:     A function to determine the next page state for a successfully loaded
+    ///                                          page.
+    /// - parameter previousPageStateForSuccess: A function to determine the previous page state for a successfully
+    ///                                          loaded page.
+    /// - parameter nextPageStateForFailure:     A function to determine the next page state for a failed page load.
+    /// - parameter previousPageStateForFailure: A function to determine the previous page state for a failed page load.
     private func pageCompletion(result result: PageResult,
                                 combine: (current: [Element], new: [Element]) -> [Element],
-                                pageEventForLoaded: (LoaderState<Element, Error>, LoaderState<Element, Error>, [Element]) -> LoaderEvent<Element, Error>,
-                                pageEventForFailed: (LoaderState<Element, Error>, LoaderState<Element, Error>) -> LoaderEvent<Element, Error>,
+                                loaderEventForLoaded: LoaderEventForStatesAndElements,
+                                loaderEventForFailed: LoaderEventForStates,
                                 nextPageStateForSuccess: PageStateForSuccess,
                                 previousPageStateForSuccess: PageStateForSuccess,
                                 nextPageStateForFailure: PageStateForFailure,

        switch result
        {
        case let .Success(loadResult):
            infoState.modify({ current in
                let newState = InfoLoaderState(
                    loaderState: LoaderState(
                        elements: combine(current: current.loaderState.elements, new: loadResult.elements),
                        nextPageState: nextPageStateForSuccess(
                            current: current.loaderState.nextPageState,
                            mutation: loadResult.nextPageHasMore
                        ),
                        previousPageState: previousPageStateForSuccess(
                            current: current.loaderState.previousPageState,
                            mutation: loadResult.previousPageHasMore
                        )
                    ),
                    nextInfo: loadResult.nextPageInfo.value ?? current.nextInfo,
                    previousInfo: loadResult.previousPageInfo.value ?? current.previousInfo
                )

                eventsPipe.1.sendNext(pageEventForLoaded(newState.loaderState, current.loaderState, loadResult.elements))

                return newState
            })

        case let .Failure(error):
            infoState.modify({ current in
                let newState = InfoLoaderState(
                    loaderState: LoaderState(
                        elements: current.loaderState.elements,
                        nextPageState: nextPageStateForFailure(
                            current: current.loaderState.nextPageState,
                            error: error
                        ),
                        previousPageState: previousPageStateForFailure(
                            current: current.loaderState.previousPageState,
                            error: error
                        )
                    ),
                    nextInfo: current.nextInfo,
                    previousInfo: current.previousInfo
                )

                eventsPipe.1.sendNext(pageEventForFailed(newState.loaderState, current.loaderState))

                return newState
            })
        }
    }
}

        )
    }


    /// Completes loading of the previous page.
    ///
    /// - parameter result: The result from loading the previous page.
    private func previousPageCompletion(result result: PageResult)
    {
        pageCompletion(
            result: result,
            combine: { current, new in new + current },
            loaderEventForLoaded: LoaderEvent<Element, Error>.PreviousPageLoaded,
            loaderEventForFailed: LoaderEvent.PreviousPageFailed,
            nextPageStateForSuccess: InfoStrategyArrayLoader.currentIfNoMutation,
            previousPageStateForSuccess: InfoStrategyArrayLoader.hasMoreIfNoMutation,
            nextPageStateForFailure: { current, _ in current },
