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].