Comments (8)
So, it turns out there's a very simple and elegant solution. Define a free monad transformer:
data FreeT f m r = FreeT { runFreeT :: m (Either r (f (FreeT f m r))) }
instance (Functor f, Monad m) => Monad (FreeT f m) where
return = FreeT . return . Left
m >>= f = FreeT $ runFreeT m >>= \x -> case x of
Left r -> runFreeT $ f r
Right a -> return $ Right $ fmap (>>= f) a
instance MonadTrans (FreeT f) where
lift = FreeT . liftM Left
The above solution is a common idiom among coroutine libraries that implement MonadTrans
instances and it correctly satisfies the monad transformer laws.
from free.
Great catch.
I've actually built the free monad transformer for a related reason in scala, but had overlooked the actual law violation taking place here.
This is awkward because the existing MonadTrans is actually quite useful but the existence of liftF kind of takes the edge off.
This is definitely a "SHOULD FIX" issue. =)
I'll push a version with it when I can get a better grasp of what downstream packages will be broken, since a major version bump requires me to push about a dozen other packages of my own and I should audit any third party dependencies as well.
from free.
It's not urgent to fix (for me, at least). I only brought it up because I discovered the exact same violation in my own pipes
library, which is basically inlines a Free
monad and has a wrong MonadTrans
instance, too. I checked your library to see how you addressed the issue and only noticed the problem that way.
In a future release I may also use the free monad transformer approach to fix the issue in pipes and if I do that I'd like to use this library as the dependency for it. So from my point of view the existence of the wrong MonadTrans
is a not a big issue and it can wait for your next major version, but a free monad transformer would be a useful addition to the library, especially since a lot of coroutine libraries are basically hand-rolling their own right now.
from free.
On Sun, Mar 25, 2012 at 11:25 AM, Gabriel439 <
[email protected]
wrote:
It's not urgent to fix (for me, at least). I only brought it up because I
discovered the exact same violation in my ownpipes
library, which is
basically inlines aFree
monad and has a wrongMonadTrans
instance,
too. I checked your library to see how you addressed the issue and only
noticed the problem that way.
We seem to have invented basically the same construction.
At ClariFi have an in-house iteratee-like library (in scala) that looks a
lot like your pipes, except we use bidirectional channels so we can sent
signals back toward the sources. This basically makes the base monad we're
working over look a lot like the base functor for a Mealy machine.
In a future release I may also use the free monad transformer approach to
fix the issue in pipes and if I do that I'd like to use this library as the
dependency for it. So from my point of view the existence of the wrong
MonadTrans
is a not a big issue and it can wait for your next major
version, but a free monad transformer would be a useful addition to the
library, especially since a lot of coroutine libraries are basically
hand-rolling their own right now.
I can definitely see the utility of it.
Hrmm. The worry that I have is that folks will then pop up to pressure me
into put the transformer version in as the default and use the type alias
approach pushed by the MTL to base Free on its implementation and I think
from a pedagogical standpoint that is a mistake, so if I do add it I'll
probably just add FreeT as a separate data type. and add its faster
Church-encoded variant as well.
Er that was a bit rambly but I hope you get the idea. =)
-Edward
from free.
I got the idea. I think a separate type is fine.
Regarding bidirectional channels, if you are using the base monad to signal back to upstream, you can implement the same behavior with unidirectional channels by having upstream yield a monadic action alongside its normal yielded value which signals to downstream its desired behavior up until the next time it is requested. This is the approach I'm currently using to safely intercept downstream termination without violating the category laws for pipes. The reason is that I can never get bidirectional channels to satisfy the identity law.
from free.
That FreeT type is exactly the same as the FreeT type from control-monad-free: http://hackage.haskell.org/packages/archive/control-monad-free/0.5.3/doc/html/Control-Monad-Free.html#g:3
from free.
Thanks for the tip! I can use that for now instead of rolling my own.
from free.
I've added FreeT and CofreeT. I've kept the illegal MonadTrans, Alternative and MonadPlus instances, but I've marked them as illegal in the comments.
from free.
Related Issues (20)
- Missing free 5 migration guide HOT 2
- Metadata revisions for 4.8 and 4.8.0.1 HOT 2
- free-5 doesn't build on old GHCs with transformers-0.4 HOT 3
- Fails with GHC-7.8.4 and installed transformers HOT 9
- Failure building free 5.0.2 with GHC 8.4.2 cross to iOS
- 'Ap' from 'Control.Applicative.Free' conflicts with 'Ap' in base-4.12
- ComonadTraced instance for CofreeT
- Add a MonadBaseControl instance for CofreeT HOT 6
- Simplify the applicative instance of Free HOT 2
- Deriving Via for several datatypes HOT 1
- Comonad f => MonadFree f (Tagged f) HOT 1
- Nu-based distributive cofree
- Add a class for free monad transformer-type things.
- Document 'Control.Monad.Free.Ap' has to work only on "commutative" monads
- Why does hoistFree have such a strict type? HOT 2
- deriving (Applicative, Monad) via GenericFreeMonad "Pure" (Free f)
- Support transformers-0.6 HOT 3
- Further simplify instances to avoid overkill *1 classes
- Dangling Links HOT 2
- `hoistFree` should be named `transFree`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from free.