-
Notifications
You must be signed in to change notification settings - Fork 0
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
Convincingly demonstrate the Monads are actually needed #3
Comments
Theoretically, I think you can get that power back with class ArrowChoice arr => ArrowAlign arr where
aligned :: (Traversable t, Align t) => arr (e, a) b -> arr (e, t a) (t b) which is closely related to my class ArrowChoice arr => ArrowKeyed arr where
keyed :: (TraversableWithIndex k t, AlignWithIndex k t) => arr (e, k, a) b -> arr (e, t a) (t b) which allows a limited form of dynamic dependencies in which it is possible to compare consecutive executions of the same dependency graph. This is very useful for my use case—build caching—but it isn’t clear if it’s useful more generally. |
I don't understand what you mean. |
Sorry, you’re technically right, but there’s a distinction I’m making I wasn’t clear about. The type of traverse :: Traversable t => (b -> arr a c) -> t b -> arr a (t c) That seems like it might be useful, but it isn’t actually nearly as useful as it seems. What you really want is an operation of this type: traverseA :: Traversable t => arr a b -> arr (t a) (t b) The trouble is, with ordinary |
Ha, yes, I see! |
I take it all back: you can get data Traversal a r b
= Done b
| Yield a !(r -> Traversal a r b)
instance Functor (Traversal a r) where
fmap f = \case
Done x -> Done (f x)
Yield v k -> Yield v (fmap f . k)
instance Applicative (Traversal a r) where
pure = Done
tf <*> tx = case tf of
Done f -> fmap f tx
Yield v k -> Yield v ((<*> tx) . k)
traversal :: Traversable t => t a -> Traversal a b (t b)
traversal = traverse (flip Yield Done)
traverseA :: (ArrowChoice arr, Traversable t) => arr (e, a) b -> arr (e, t a) (t b)
traverseA f = second (arr traversal) >>> go where
go = proc (e, as) -> case as of
Done bs -> returnA -< bs
Yield a k -> do
b <- f -< (e, a)
go -< (e, k b) I have not been able to find this in any existing literature, but it might be well-known, and I just wasn’t looking in the right places. |
Once upon a time, Edward Kmett told me how to apply a lens to an arrow. The idea is that you can use Functor f => (a -> f b) -> c -> f d into Arrow p => LensLike (Context a b) s t a b -> p a b -> p s t (using only the Applicative f => (a -> f b) -> c -> f d into Arrow p => LensLike (Traversal a b) s t a b -> p a b -> p s t using only the |
Ah, https://pursuit.purescript.org/packages/purescript-profunctor-lenses/5.0.0/docs/Data.Lens.Types#t:Traversal and https://pursuit.purescript.org/packages/purescript-profunctor-lenses/5.0.0/docs/Data.Lens.Internal.Wander#t:Wander suggest that it's |
Anyway, the executive summary is that this is an application of a profunctor-style traversal. |
I think "Selective Applicative Functors" are very close to ArrowChoice.
I think the basic idea is graphs created dynamically that really only make finite choices can be squashed into one giant static graph that includes the decision tree on the previously-dynamic decisions. |
I believe that the following is the same construction as Alexis's (though I haven't actually carried out the analysis to verify that!) |
Yeah that looks like the same construction. I would do it different with https://hackage.haskell.org/package/categories-style classes, but that is a fine way to do it with Arrow as it exists today. To get back to your original question while Monad i more powerful, I think it's wildly overused, and we shouldn't feel dangerously heretical coming to conclusion that other weaker classes will almost always do. |
So that is minor evidence against our hypothesis that Monads are actually needed. |
What do we really want
Monad
for that we can't do withArrowChoice
?The text was updated successfully, but these errors were encountered: