On 2012-03-11 14:46, Paolo Capriotti wrote:
On Sun, Mar 11, 2012 at 1:25 PM, Twan van Laarhoven<twa...@gmail.com> wrote:
I would expect that
(id>>> unawait x)>>> await !== unawait x>>> await === return x
There are several type errors in this equation, so I'm not exactly
sure what you mean. If you intended to write something like:
(id>>> (unawait x>> return y))>>> await
!==
(unawait x>> return y)>>> await
then I disagree, because both sides should evaluate to 'return y'. I'm
not sure why you would expect x to be returned, since there is no
'await' after 'unawait' in the middle pipe.
Oops, I got confused by (>>) and (>>>). The intended semantics of unawait is
unawait x >> await === return x
So what I was trying to write is
(id >+> unawait x) >> await
=== {by identity law}
unawait x >> await
=== {by behavior of unawait}
return x
But that this is impossible to implement, and instead what you get is
(id >+> unawait x) >> await === return () >> await === await
because in the general case of
(p >>> unawait x)
if is impossible to transform the unawaited value out of the composition.
Why? The natual definition would be:
p >+> (unawait x >> p') == (yield x >> p) >+> p'
Right, but then take p==id, which gives
(id >+> (unawait x >> return ())) >> p'
===
((yield x >> id) >+> return ()) >> p'
===
return () >> p'
===
p'
So the unawait is not seen by p', whereas the identity law would give
(id >+> (unawait x >> return ())) >> p'
===
(unawait x >> return ()) >> p'
===
unawait x >> p'
I would like to get this latter semantics, and if the left side is id, it is
fine. However, in
(p :: Pipe a b r) >+> (unawait x >> q :: Pipe b c r) :: Pipe a c r
x has type b. You can not write this in a form like
unawait x' >> q :: Pipe a c r
because here x' would have type a. But if p == id, this is exactly what you
would like to get.
I'm extremely wary of this sort of reasoning, because failure of
invariants in simple situations are a symptom of something being
conceptually wrong in the abstraction.
Or perhaps we should be satisfied when Pipe is a Semigroupoid?
I don't think so, since we can always add formal identities. Usually,
though, failure of the identity law implies failure of associativity,
by just putting the "failing identity" in the middle of a composition.
A simple way to implement unawait that fails the identity law is by discarding
left-over unawaits inside a vertical composition. I.e.
unawait x >+> p === return () >+> p
q >+> unawait y === q >+> return ()
As long as you do this consistently for *all* vertical compositions, I don't see
how associativity is broken.
In the first case, with unawait on the left, you don't need to discard the
await. But I think it is probably more consistent if you do.
Anway, 'purePipe id' is now a failing identity, in the sense that composing with
it discards trailing awaits from the other thing composed with.
Twan
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe