I'm building a couple of DSLs which should be composable based on 'free monads' and 'datatypes a la carte', using the free and compdata packages (similar in spirit to Combining Free types).
Whilst this works for some simple DSLs, I'm stuck on one which has a type parameter, in the case of a constructor/command which doesn't depend on this type parameter, causing an ambiguous type parameter error from GHC.
To clarify, here's some code:
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
module DSL where
import Data.Comp
import Control.Monad.Free
type Index = Int
data DSL a next = Read Index (a -> next)
| Write a (Index -> next)
| GetLastIndex (Index -> next)
deriving (Functor)
read :: (Functor f, DSL a :<: f, MonadFree f m) => Index -> m a
read idx = liftF (inj (Read idx id))
write :: (Functor f, DSL a :<: f, MonadFree f m) => a -> m Index
write a = liftF (inj (Write a id))
-- This works
getLastIndex' :: MonadFree (DSL a) m => m Index
getLastIndex' = liftF (GetLastIndex id)
-- This doesn't:
--
-- Could not deduce (Data.Comp.Ops.Subsume
-- (compdata-0.10:Data.Comp.SubsumeCommon.ComprEmb
-- (Data.Comp.Ops.Elem (DSL a0) f))
-- (DSL a0)
-- f)
-- from the context (Functor f, DSL a :<: f, MonadFree f m)
-- bound by the type signature for
-- getLastIndex :: (Functor f, DSL a :<: f, MonadFree f m) => m Index
-- at simple.hs:30:17-66
-- The type variable ‘a0’ is ambiguous
-- In the ambiguity check for the type signature for ‘getLastIndex’:
-- getLastIndex :: forall (m :: * -> *) (f :: * -> *) a.
-- (Functor f, DSL a :<: f, MonadFree f m) =>
-- m Index
-- To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
-- In the type signature for ‘getLastIndex’:
-- getLastIndex :: (Functor f, DSL a :<: f, MonadFree f m) => m Index
getLastIndex :: (Functor f, DSL a :<: f, MonadFree f m) => m Index
-- getLastIndex = liftF (inj (GetLastIndex id))
getLastIndex = _
Trying to get this to work with enabling the AllowAmbiguousTypes extension as hinted by GHC didn't get me any further. I tried adding some forall a-style things in the type signature, to no avail.
Is there any way to get this pattern to work?