Skip to content
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

MonadIO Type Constraint #1

Closed
ori-sky opened this issue Aug 28, 2015 · 1 comment
Closed

MonadIO Type Constraint #1

ori-sky opened this issue Aug 28, 2015 · 1 comment

Comments

@ori-sky
Copy link

ori-sky commented Aug 28, 2015

First of all, my apologies if I don't fully understand the code behind ObjectName -- I'm unsure as to whether or not the change I'm about to request is possible.

I've been considering making use of the typeclasses defined in Data.ObjectName in a project I'm working on; however, I noticed there is a type constraint of MonadIO on the type variable m rather than a looser constraint of Monad m. I wondered if this is out of necessity or by design and also wondered if such a change might be considered if it is possible, as it would be useful to generate object names in a pure monadic context such as State.

In short, is it possible to change the constraint MonadIO m to simply Monad m to allow instances of ObjectName and GeneratableObjectName to be written within non-IO monads?

@svenpanne
Copy link
Owner

Let's consider an extremely simple example:

data Foo = Foo

isFoo :: Foo -> IO Bool
isFoo _ = return True

deleteFoo :: Foo -> IO ()
deleteFoo _ = return ()

So Foo is a name for some kind of objects, and its related predicate and its deletion function live in the IO monad, something which e.g. is the common case for OpenGL-related names. Now assume that following your proposal ObjectName uses Monad m instead of MonadIO m. Then the following will not type-check:

instance ObjectName Foo where
  isObjectName = isFoo
  deleteObjectName = deleteFoo

The reason for this is that isFoo has a more specific type than isObjectName requires: isFoo only works for IO, not for all monads. BTW: This has nothing to do with the fact that isObject name is part of a class, the same type-checking error would happen everywhere a type signature is more general than the principal type of the value it refers to: [True] :: [a] is wrong, while e.g. [] :: [Int] is OK. Remember that all free type variables are universally quantified, include the type variables in contexts.

The current context MonadIO m is a bit more specific than plain Monad m, the former requires a monad in which IO actions can be embedded. This way, one can easily make Foo an instance of ObjectName:

instance ObjectName Foo where
  isObjectName = liftIO . isFoo
  deleteObjectName = liftIO . deleteFoo

In a nutshell: With your proposal one would have a hard time making any sensible instances at all, because things would have to work for all monads. With multi-parameter type classes and functional dependencies you can achieve what you want, but that's not what ObjectName is for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants