Skip to content

Instantly share code, notes, and snippets.

@escherlies
Created February 24, 2023 09:58
Show Gist options
  • Save escherlies/2ec3cdfd517704432edfa753b6627d02 to your computer and use it in GitHub Desktop.
Save escherlies/2ec3cdfd517704432edfa753b6627d02 to your computer and use it in GitHub Desktop.
An Elm context type that can be run everywhere. Like a Reader.
module Context exposing (..)
type Context a b
= WithContext (a -> b)
withContext : (a -> b) -> Context a b
withContext =
WithContext
runContext : Context a b -> a -> b
runContext (WithContext fn) a =
fn a
@escherlies
Copy link
Author

Suppose you have a api context:

type alias ApiEnv a =
    { a | api : { url : String } }

then you can define your requests for example like

upload : File.File -> (Result Http.Error String -> msg) -> Context (ApiEnv a) (Cmd msg)
upload file uploaded =
    withContext
        (\ctx ->
            Http.request
                { method = "POST"
                , headers = []
                , url = ctx.api.url ++ "/uploads"
                , body =
                    Http.multipartBody
                        [ Http.filePart "file" file
                        ]
                , expect = Http.expectString uploaded
                , timeout = Nothing
                , tracker = Just (File.name file)
                }
        )

and in your update function when you call the command:

 runContext (Api.upload file (Uploaded << Result.mapError HttpError)) model.env -- :: Cmd Msg

where model.env incorporates the composed AppEnv.

@escherlies
Copy link
Author

Upon further discussion, this actually is a Reader. 😄

See Punie/elm-reader

With open records as environment, the environments can be composed and scoped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment