-
Notifications
You must be signed in to change notification settings - Fork 65
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
makeOps for free! #29
Comments
I'm not sure I see how the |
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":
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. |
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 |
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 data Bar a = Bar a (String -> a)
bar :: MonadFree Bar m => m (Maybe String) |
@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. |
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. |
Digging into gist by @bgamari, I got working code for simplest cases https://gist.github.com/fizruk/7441605. |
I'd be okay with adding it directly to the package here if folks want it. |
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). |
Closing this as it is merged in. |
Currently anyone using free monads is forced to write some boilerplate code, e.g.:
I'd be happy to substitute that with:
I'm not sure this can be done in general, but there certainly is some pattern we could probably use. I am not familiar with TH enough to implement the idea right now.
Also I guess this TH stuff should be placed in a separate package?
The text was updated successfully, but these errors were encountered: