## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ## ----------------------------------------------------------------------------- library(chronicler) ## ----parsermd-chunk-2--------------------------------------------------------- my_sqrt <- function(x){ sqrt(x) } ## ----parsermd-chunk-3--------------------------------------------------------- my_sqrt <- function(x, log = ""){ list(sqrt(x), c(log, paste0("Running sqrt with input ", x))) } ## ----parsermd-chunk-4--------------------------------------------------------- my_log <- function(x, log = ""){ list(log(x), c(log, paste0("Running log with input ", x))) } ## ----parsermd-chunk-5--------------------------------------------------------- 10 |> sqrt() |> log() ## ----parsermd-chunk-6, eval = FALSE------------------------------------------- # 10 |> # my_sqrt() |> # my_log() # ## ----parsermd-chunk-7--------------------------------------------------------- log_it <- function(.f, ..., log = NULL){ fstring <- deparse(substitute(.f)) function(..., .log = log){ list(result = .f(...), log = c(.log, paste0("Running ", fstring, " with argument ", ...))) } } ## ----parsermd-chunk-8--------------------------------------------------------- l_sqrt <- log_it(sqrt) l_sqrt(10) l_log <- log_it(log) l_log(10) ## ----parsermd-chunk-9--------------------------------------------------------- bind <- function(.l, .f, ...){ .f(.l$result, ..., .log = .l$log) } ## ----parsermd-chunk-10-------------------------------------------------------- 10 |> l_sqrt() |> bind(l_log) ## ----parsermd-chunk-11-------------------------------------------------------- log(sqrt(10)) ## ----parsermd-chunk-12-------------------------------------------------------- unit <- log_it(identity) ## ----parsermd-chunk-13-------------------------------------------------------- fmap <- function(m, f, ...){ fstring <- deparse(substitute(f)) list(result = f(m$result, ...), log = c(m$log, paste0("fmapping ", fstring, " with arguments ", paste0(m$result, ..., collapse = ",")))) } ## ----parsermd-chunk-14-------------------------------------------------------- # Let’s use unit(), which we defined above, for this. (m <- unit(10)) ## ----parsermd-chunk-15-------------------------------------------------------- fmap(m, log) ## ----parsermd-chunk-16-------------------------------------------------------- fmap(m, l_log) ## ----parsermd-chunk-17-------------------------------------------------------- flatten <- function(m){ list(result = m$result$result, log = c(m$log)) } ## ----parsermd-chunk-18-------------------------------------------------------- flatten(fmap(m, l_log)) ## ----parsermd-chunk-19-------------------------------------------------------- # I first define a composition operator for functions `%.%` <- \(f,g)(function(...)(f(g(...)))) # I now compose flatten() and fmap() # flatten %.% fmap is read as "flatten after fmap" flatmap <- flatten %.% fmap ## ----parsermd-chunk-20-------------------------------------------------------- 10 |> l_sqrt() |> bind(l_log) ## ----parsermd-chunk-21-------------------------------------------------------- 10 |> l_sqrt() |> flatmap(l_log) ## ----parsermd-chunk-22-------------------------------------------------------- # Since I'm using `{purrr}`, might as well use purrr::compose() instead of my own implementation flatmap_list <- purrr::compose(purrr::flatten, purrr::map) # Functions that return lists: they don't compose! # no worries, we implemented `flatmap_list()` list_sqrt <- \(x)(as.list(sqrt(x))) list_log <- \(x)(as.list(log(x))) 10 |> list_sqrt() |> flatmap_list(list_log) ## ----parsermd-chunk-23-------------------------------------------------------- a <- as_chronicle(10) r_sqrt <- record(sqrt) testthat::test_that("first monadic law", { testthat::expect_equal(bind_record(a, r_sqrt)$value, r_sqrt(10)$value) }) ## ----parsermd-chunk-24-------------------------------------------------------- testthat::test_that("second monadic law", { testthat::expect_equal(bind_record(a, as_chronicle)$value, a$value) }) ## ----parsermd-chunk-25-------------------------------------------------------- a <- as_chronicle(10) r_sqrt <- record(sqrt) r_exp <- record(exp) r_mean <- record(mean) testthat::test_that("third monadic law", { testthat::expect_equal( ( (bind_record(a, r_sqrt)) |> bind_record(r_exp) )$value, ( a |> (\(x) bind_record(x, r_sqrt) |> bind_record(r_exp))() )$value ) }) ## ----parsermd-chunk-26-------------------------------------------------------- r_sqrt <- record(sqrt) r_exp <- record(exp) r_mean <- record(mean) a <- 1:10 |> r_sqrt() |> bind_record(r_exp) |> bind_record(r_mean) flatmap_record <- purrr::compose(flatten_record, fmap_record) b <- 1:10 |> r_sqrt() |> flatmap_record(r_exp) |> flatmap_record(r_mean) identical(a$value, b$value)