What is the best way to do streaming in your free algebra?

I experimented with creating an HTTP client using Free monads, similar to the approach taken in a conversation by Runnar Bjarnason, Compiled application architecture with reasonable low-cost monads .

What I still have can be seen in this snippet, https://bitbucket.org/snippets/atlassian-marketplace/EEk4X .

Everything is working fine, but I'm not completely satisfied. The biggest point of pain is caused by the need to parameterize HttpOpsover the algebra into which it will be embedded in order to provide a stream representation of the request and response bodies. It makes it impossible to create your algebra simply by saying

type App[A] = Coproduct[InteractOps, HttpcOps[App, ?], A]

If you try, you will get an error illegal cyclic referencefrom the compiler. To solve this problem you can use case class

type App0[A] = Coproduct[InteractOps, HttpcOps[App, ?], A]   
case class App[A](app0: App0[A])

This solves the problem of cyclic task, but introduces a new problem. We no longer have instances Inject[InteractOps, App], which means we no longer have instances Interact[App]and Httpc[HttpcOps[App, ?]]therefore we must manually define them for our algebra. For a small and simple algebra such as this, this is not too burdensome, but for something more, it can turn into many patterns.

Is there any other approach that would allow us to enable stream and layout of algebras in a more convenient way?

+4
source share
1 answer

, , App . , , :

App(inj(Send(
  Request(GET, uri, v, hs,
          StreamT(App(inj(Send(
            Request(GET, uri, v, hs,
                    StreamT(App(inj(Tell("foo")))))))))))))

, EntityBody - HTTP-, . , , .

:

case class Ask[A](k: String => A)
case class Req[F[_],A](k: Process[Ask, String] => A)
type AppF[A] = Coproduct[Ask, Req[Ask,?], A]
type App[A] = Free[AppF, A]

Req (scalaz.stream.Process) String s. - (, HTTP- ). , App, Req Req s.

+3

Source: https://habr.com/ru/post/1613122/


All Articles