Comments (11)
I'm not sure I see how the input
definition could be mechanically derived.
from free.
Basically a data type representing underlying functor looks like that:
data T next = C1 u v w | C2 x y z | ...
For each constructor we want to define an appropriate "free operation":
- operation name is derived by lowering the first letter:
Op => op
,SomeCtor
=>someCtor
; - if constructor has arguments that don't depend on
next
they are used as arguments to the corresponding operation; - if constructor does not have arguments that depend on
next
then the operation is of typeop :: (MonadFree f m) => b -> c -> ... -> m a
and is defined simply asop x ... z = liftM $ Op x ... z
; - for each argument for constructor that depend on
next
the following rules are applied:next
goes to()
a -> next
goes toid
a -> b -> next
goes to(,)
- similarly,
a -> ... -> z -> next
goes to(,,...,)
- for arbitrary type
T
rules apply recursively with 2 considerations:- a tuple
(a, b, ..., z)
should be seen as separate "arguments"a
,b
, ...,z
if any of components usenext
; - alternatives in types like
Either
should result in branching operations, e.g.:
- a tuple
data MyOps next
= Move (MoveDir next)
| Stop
data MoveDir next
= Left next
| Right next
| Down next
| Up next
-- automatic derivation of operations for `MyOps` should result in 5 operations
-- names are derived by appending constructor names
moveLeft = ...
moveRight = ...
moveUp = ...
moveDown = ...
stop = ...
The last thing is debatable (about sum types). I hope this covers most of uses.
from free.
Here are some examples with desired derivations:
data F next
= Done
| Failure String
| Delay next
| Output String next
| Input (String -> next)
| GetMsg (Int -> String -> next)
| Prompt String (String -> next)
| Branch next next
| Cont ((next -> Int) -> Int)
| Doing (Maybe next)
deriving (Functor)
-- desired derivations
done :: MonadFree F m => m a
done = liftF Done
failure :: MonadFree F m => String -> m a
failure s = liftF $ Failure s
delay :: MonadFree F m => m ()
delay = liftF $ Delay ()
output :: MonadFree F m => String -> m ()
output s = liftF $ Output s ()
input :: MonadFree F m => m String
input = liftF $ Input id
getMsg :: MonadFree F m => m (Int, String)
getMsg = liftF $ GetMsg (,)
prompt :: MonadFree F m => String -> m String
prompt s = liftF $ Prompt s id
branch :: MonadFree F m => m ()
branch = liftF $ Branch () ()
cont :: (MonadFree F m) => m ()
cont = liftF $ Cont (\k -> k ())
doingNothing :: MonadFree F m => m a
doingNothing = liftF $ Doing Nothing
doingJust :: MonadFree F m => m ()
doingJust = liftF $ Doing $ Just ()
I still don't know how to handle recursive definitions (or should they be handled). E.g. for [a]
or Tree a
.
from free.
Things are complicated when one considers cases such as,
data Foo a = Foo (String -> a) (Int -> a)
In this case you might want the operation to be something like,
foo :: MonadFree Foo m => m (Either String Int)
but in general it won't be possible to construct a sum type like this.
For now it'll be sufficient to consider the simple cases like Foo
and,
data Bar a = Bar a (String -> a)
bar :: MonadFree Bar m => m (Maybe String)
from free.
@fizruk brought up the point that one could also derive cases like,
data Bar' a = Bar' a a (String -> a)
bar' :: MonadFree Bar' m => m (Maybe a)
bar' = Bar' Nothing Nothing Just
It's not entirely clear that we want to do this however.
from free.
I started working on this today in an effort to avoid writing a talk. The (currently broken) state of things can be found here. I'll keep updating this as I do more work on it.
from free.
Digging into gist by @bgamari, I got working code for simplest cases https://gist.github.com/fizruk/7441605.
from free.
Okay, I believe now this supports most of the basic stuff (the code should be refined though).
@ekmett, what do think about all this? Where should such a thing be placed? Control.Monad.Free.TH
or a separate package (e.g. free-derive
)?
from free.
I'd be okay with adding it directly to the package here if folks want it.
from free.
Interestingly, there is another kind of operations which could also be derived automatically. Consider this:
data Expr e
= Lit Int
| Add e e
deriving (Functor)
lit :: MonadFree Expr m => m a
lit x = wrap $ Lit x
add :: MonadFree Expr m => m a -> m a -> m a
add x y = wrap $ Add x y
Those can be used like that:
data Term = Free Expr Void
test :: Term
test = add (lit 4) (lit 5)
I don't use these operations, so I can't see if automatic generation for them is needed (but perhaps would be useful).
from free.
Closing this as it is merged in.
from free.
Related Issues (20)
- 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`
- MonadAccum instance
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.