
Hello, For testing purposes, I am trying to make an overlay to IO which carries a phantom type to ensure a context. I define contexts using empty type classes : class CtxFoo c class CtxBar c The overlay : newtype MyIO c a = MyIO (IO a) Then I define some methods that run only a specific context : runFoo :: (CtxFoo c) => MyIO c a -> IO a runFoo (MyIO x) = x runBar :: (CtxBar c) => MyIO c a -> IO a runBar (MyIO x) = x And then an action that runs in context 'Foo' : someAction :: (CtxFoo c) => MyIO c () someAction = putStrLn "FOO" Then I run it : main = runFoo someAction But obiously, GHC complains that my type 'c' remains uninstantiated : Ambiguous type variable `c' in the constraint: (CtxFoo c) arising from a use of `runFoo' Probable fix: add a type signature that fixes these type variable(s) In the expression: runFoo someAction In an equation for `main': main = runFoo someAction Is there a way to deal with this ? The interest of using type classes and not empty types to represent the contexts is that it stays simple, and that I can do that : someAction2 :: (CtxFoo c, CtxBar c) => MyIO c () someAction2 = putStrLn "FOO and BAR" ... a function that can run in both contexts.