
On Monday 02 November 2009 2:56:45 pm Dan Weston wrote:
It seems to me that Tomorrow cannot be parametrically polymorphic, or else I could wrap it again (Tomorrow (Tomorrox x)). An unwrapping fixpoint operator needs to reflect the type to know when not to go too far. One solution is to guarantee that it can go as far as it wants with a comonad (stopping when the function argument wants to, not when the data type runs out of data):
He isn't worried about people putting things off; he's worried about people using things sooner than they're ready. So:
import Control.Comonad import Control.Monad.Fix
tfix :: Comonad tomorrow => (tomorrow x -> x) -> x tfix = extract . (\f -> fix (extend f))
This doesn't achieve his goals, because: tfix extract tries to get the 'x' from tomorrow and give it to you today, which is bad, and of course: tfix extract = extract (fix (extend extract)) = extract (fix id) = extract _|_ =? _|_ Rather, the aim is to give you a promise of something tomorrow, so that you can build a structure made of something today, followed by something tomorrow. That is, roughly, enforcing the productive construction of a circular object. Such a productive process is given the object 'in the future', and it must produce something now, followed (in time) by operations on the future whole. And the problem with monads is that Tomorrow (Tomorrow x) is something that happens in two days, but join is supposed to make it happen tomorrow instead.
To quote Cabaret, if tomorrow belongs to me, then surely the day after belongs to me as well.
Otherwise, to stop the fixpoint, it seems you need a more restricted type to encode some stopping sentinel (my own parametrically polymorphic attempts all end in infinite types, so maybe ad hoc polymorphism or a type witness is needed?)
Do you have a blog post on this problem?
He does, in fact: http://www.e-pig.org/epilogue/?p=186 Cheers, -- Dan