Providing an abstraction over a library

Hi! At work we see a recurring pattern:

  • We use a library (e.g. dhall-aws-cloudformation).

  • We want to provide abstractions over this library (e.g. “a Lambda Function that transforms one Kafka topic into another”).

  • We provide a record schema for the abstraction, and a Dhall function implementing that abstraction, usually following this pattern:

    let Args = { Type = {...}, default = {...} }
    let call = (\args : Args.Type) -> UnderlyingLibraryType::{...}
    in { Args, call }
    
  • We use the abstraction with MyAbstraction.call MyAbstraction.Args::{...}.

The repeated boilerplate makes me wonder:

  • Is there a better way to do what we’re doing?
  • Is there an existing proposal for syntax that would remove some boilerplate from this pattern?
  • Should we make such a proposal if it doesn’t exist?

Do you have some pseudocode for the simpler syntax that you have in mind?

Do you have some pseudocode for the simpler syntax that you have in mind?

My initial thought was something like MyAbstraction.call::{...} but that introduces visual (if not technical) ambiguity about what call is. But after playing with this for a while, I reckon our problem was that we were not designing our types well. What we were calling Args should have been a real type that represented something, not just the anonymous cluster of things required to make something else.

As for “a lambda function that transforms one kafka topic into another” we’re moving toward a pattern of (endo)functions that add capabilities to things, instead of making a separate type for every variation.