
Heinrich Apfelmus wrote:
Sebastian Fischer wrote:
For example, the implementation of `callCC` does not type check with your changed data type.
[snip]
As for the interaction: what should
((callCC ($ 0) >> mzero) `orElse` return 2) >>= return . (+3)
be? If the scope of callCC should not extend past orElse , then this evaluates to return 5 . But this choice of scope dictates the type that Holger mentioned.
If the the scope of callCC should extend beyond the orElse , so that the whole thing evaluates to mzero , orElse will have the type of mplus . But then, I think that your implementation type CMaybe needs to be more sophisticated because orElse now needs to detect whether the argument contains a call to callCC or not in order to distinguish
((callCC ($ 0) >> mzero) `orElse` return 2) >>= return . (+3)
==> mzero
from
(mzero `orElse` return 2) >>= return . (+3)
==> return 5
Out of curiosity, I've implemented these semantics with operational . Code attached. Took me a while to figure out how to implement callCC , but it turns out to be straightforward if you simply carry around the current continuation as an additional parameter. It doesn't seem to be possible to implement this with just the CMaybe r a type, in particular since the implementation I gave cannot be refunctionalized to said type. In other words, there is probably no associative operation orElse :: CMaybe r a -> CMaybe r a -> CMaybe r a with identity `mzero` that satisfies the cancellation law. I don't have a proof, but the argument that it doesn't interact well with the default implementation of callCC seems strong to me. Regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com