-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why is the n
of hoist
not a monad?
#11
Comments
See this StackOverflow question and answer, which explain the rationale behind this. The quick summary is: this keeps constraints smaller and I haven't (yet) encountered an instance that required the |
Well, you have one now. I must note that the alternative |
instance MFunctor Deserialize where
hoist nat (Deserialize k) = Deserialize (nat . liftM (hoist nat) . k)
instance MFunctor Result where
hoist nat (Fail str bs) = Fail str bs
hoist nat (Partial k) = Partial (nat . liftM (hoist nat) . k)
hoist nat (Done a bs) = Done a bs |
Wow! Tunnel vision... Okay thanks. |
No problem at all! :) |
Here's another example: type f ⥴ g = ∀ a. f a → g a
unViewTransT
∷ ∀ instr f g α.
( Monad f
, Monad g
)
⇒ (f ⥴ g)
→ f (ProgramViewT instr f α)
→ ProgramT instr g α
unViewTransT η = join ∘ lift ∘ η ∘ (return ∘ go =≪)
where
go ∷ ProgramViewT instr f α → ProgramT instr g α
go (m :>>= k) = singleton m ≫= unViewTransT η ∘ viewT ∘ k
go (Return a) = return a
hoist
∷ ( Monad f
, Monad g
)
⇒ (f ⥴ g)
→ (ProgramT instr) f β
→ (ProgramT instr) g β
hoist η = unViewTransT η ∘ viewT I don't see another way to do this since |
I tried my hand at this, and I don't think it's possible unless |
Thanks for looking at this. Indeed, the main difficulty here seems to be that the internals of I saw your comment about wanting to minimize constraints. I'm curious though, have you found many cases where requiring a |
Well, in this case I don't mind relying on it having access to the internal representation since it would be an orphan instance otherwise. However, even without that internal access, it still makes sense for |
Good point. I suppose the desire to avoid orphan instances does make this more of an issue for the library author… And I agree that an inverse to |
Here's another one: the hoistFT :: (Monad m, Monad n) => (forall a. m a -> n a) -> FT f m b -> FT f n b
hoistFT phi (FT m) = FT (\kp kf -> join . phi $ m (return . kp) (\xg -> return . kf (join . phi . xg))) If there's a way to weaken that to |
@treeowl: Yeah, for the efficient implementation you require the The problem is that adding the |
I don't think you can convert back.
…On May 21, 2017 10:36 PM, "Gabriel Gonzalez" ***@***.***> wrote:
@treeowl <https://github.com/treeowl>: Yeah, for the efficient
implementation you require the Monad n constraint. In theory you can
still do it inefficiently by converting to Control.Monad.Trans.Free.FreeT
and then converting back
The problem is that adding the Monad n constraint breaks the
Control.Monad.Trans.Compose module
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#11 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABzi_TaXl1X99SN6VnAPQQD2LcmJEKVQks5r8PSVgaJpZM4BhqFj>
.
|
You can, using |
While this isn't quite complete, one option is to use instance (MFunctor f, MonadTrans f, Lifting Monad g, MonadTrans g) => MonadTrans (ComposeT f g)
where
lift :: forall m a. Monad m => m a -> ComposeT f g m a
lift = ComposeT . hoist lift . lift \\ (lifting :: Monad m :- Monad (g m)) This requires a |
I don't understand what this polykinded thing has to do with monad
morphisms. The `rmap` example seems a bit silly, since `hoist` is already
too restrictive to do everything `rmap` can.
…On Thu, Aug 24, 2017 at 10:34 PM, Gabriel Gonzalez ***@***.*** > wrote:
@treeowl <https://github.com/treeowl>: There's yet another issue, which
is that adding a Monad n constraint will break the use case that fixing
#29 <#29> was
designed to solve (i.e. the case where n has kind k -> *). Adding the Monad
n constraint would force k to be *, defeating the purpose of making the
class poly-kinded
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#11 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABzi_dN5kINPOb87S4jtMUvVMD5K1WYyks5sbjKbgaJpZM4BhqFj>
.
|
Either way, adding the I also would still like to keep the constraints on the use of |
Actually, even without considering |
I just stumbled over the unviewT :: Monad n => ProgramViewT instr n a -> ProgramT instr n a
unviewT (Return a) = return a
unviewT (instruction :>>= continuation) = singleton instruction >>= continuation ...you still need the EDIT: I meant |
@turion: I believe you can implement instance MFunctor (ProgramT instr m) where
hoist nat (Lift m) = Lift (nat m)
hoist nat (Bind m f) = Bind (hoist nat m) (\x -> hoist nat (f x))
hoist _ (Instr i) = Instr i I have not type-checked that, though |
You are right indeed! Thank you very much. |
You're welcome! 🙂 |
I mean, why
instead of
?
I've stumbled upon that trying to implement
MMonad
in terms of this function.The text was updated successfully, but these errors were encountered: