On 5/2/14, 3:27 PM, Kai Wang wrote:
Thanks for the hint. Please correct if I'm wrong.

In this approach, we essentially encode all possible inputs/output of Model as a

(Either (Either (Either .... (((Either A B) C) D) .... X) Y) Z) Void).

- Will the nested Either's have a performance penalty?

Yes, they will have a performance penalty (O(N), where N is the depth of the service you are using). I don't know a tasteful solution that fixes this problem. Maybe Oliver knows more about this since I know he specializes in advanced type system features and also effect systems.

Alternatively, maybe there's a more elegant solution that I'm missing.

- Does it make sense to make use of the state in Model? ie. should the 'serve' be something like this?

    serve
        :: (reqLocal -> FreeT remote (State s) respLocal)
        -- 'FreeT f (State s)' instead of 'Free'
-> Model s (reqLocal :+: OutputsOf remote) (respLocal :+: InputsOf remote)


Yes, it definitely does make sense.  I just forgot about it.

- This might sound silly, but how do I actually write the 'serve' function? I reckon I'm supposed to write a Pipe that awaits an input, check if it's local or remote. How do I actually put these together?

    serve
        :: (reqLocal -> FreeT remote (State s) respLocal)
-> Model s (reqLocal :+: OutputsOf remote) (respLocal :+: InputsOf remote)
    serve f = asPipe $ do
        result <- await
        case of result of
            Left local -> undefined -- run Free
            Right Remote -> undefined -- continue run Free


Actually, my original idea was slightly incorrect. You need to make `InputsOf` and `OutputsOf` associated type families of a type class with `serve` as a method of the type class. In other words, you need something like this:

    class Serve remote where
        type family OutputsOf remote
        type family InputsOf remote

        serve
:: (reqLocal -> FreeT remote (State s) respLocal)
-> Model s (reqLocal :+: OutputsOf remote) (respLocal :+: InputsOf remote)

Then the meat of the logic is implementing the following two instances of the `Serve` class:

    instance Serve VoidF where...

    instance Serve (CoProduct f g) where ...-- The hard part

If that's too tricky, I will be trying it myself anyway very soon.

As a final note, we will probably also need to attach `Int` tokens to requests and responses to identify which "thread" of our model the request or response belongs to, so the above type will need further tweaking. Remember that our model is going to be purely simulating multiple "handler threads" at once (one per each request the server is actively servicing), so we need a way to distinguish their requests and responses from each other.


On Friday, May 2, 2014 11:32:39 AM UTC-7, Michael Thompson wrote:

    For some reason `ghc` isn't noticing the possibility that
    arguments to `OutputsOf` are meant to be of kind (* -> *).

    There is probably some simpler way of getting it to notice the
    possibility, but if you add something like

         {-#Language KindSignatures#-}

    then you can write

         type family OutputsOf (f :: * -> *) :: *

    and similarly for `InputsOf`. Then it compiles
    http://lpaste.net/5936788157725933568
    <http://lpaste.net/5936788157725933568>



--
You received this message because you are subscribed to the Google Groups "Haskell Pipes" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[email protected]>.

--
You received this message because you are subscribed to the Google Groups "Haskell 
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].

Reply via email to