Here is a quick example sketch of wrapping Http calls in request objects
and delaying conversion to commands. Untested but it compiles. (The tricky
part was handling the decoder since we need to bury the decoded type.)

type alias HttpResult a =
  Result Http.Error a

makeStringTagger : Json.Decode.Decoder a -> (HttpResult a -> msg) ->
(HttpResult String -> msg)
makeStringTagger decoder tagger =
    stringDecoder =
      Json.Decode.decodeString decoder
      >> Result.formatError Http.UnexpectedPayload
    \result -> Result.andThen result stringDecoder |> tagger

type Request msg
  = Get String (HttpResult String -> msg)
  | Command (Cmd msg)
  | Batch (List (Request msg))

get : (Result Http.Error a -> msg) -> String -> Json.Decode.Decoder a ->
Request msg
get tagger url decoder =
  Get url (makeStringTagger decoder tagger)

command : Cmd msg -> Request msg
command =

batch : List (Request msg) -> Request msg
batch =

-- We need mapping support for Requests just like Cmds.

map : (a -> b) -> Request a -> Request b
map fn request =
  case request of
    Get url tagger ->
      Get url (tagger >> fn)
    Command cmd ->
      Command <| fn cmd
    Batch list ->
      Batch <| (map fn) list

-- At the service layer, we need to map back out to Cmds

toCmd : Request msg -> Cmd msg
toCmd request =
  case request of
    Get url tagger ->
      Http.getString url
      |> Task.toResult
      |> tagger
      |> Task.perform (Debug.crash "never fail") identity
    Command cmd ->
    Batch list ->
      Cmd.batch <| toCmd list


On Fri, Oct 14, 2016 at 4:17 PM, Mark Hamburg <> wrote:

> I think the requests-as-an-alternative-to-commands pattern would serve
> you here. (Sorry no link but there was a more detailed example a while
> back.)
> Basically, you create a type that parallels Cmd in that it supports batch
> and map functionality and you have it embody the notion of making HTTP
> requests. When the requests get to your service layer, they get turned into
> actual HTTP Cmds with the appropriate auth token attached. (Your request
> type should also allow wrapping normal Cmds so that you can pass those
> through as well.)
> This pattern essentially handles "middleware" as an outer wrapper on the
> model standing between your "real" model and the outside world.
> Mark

You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
For more options, visit

Reply via email to