我正在使用free和compdata包(在精神上类似于Combining Free types )构建几个 DSL,它们应该可以基于“free monads”和“datatypes a la carte”进行组合。
虽然这适用于一些简单的 DSL,但在构造函数/命令不依赖于该类型参数的情况下,我被困在一个具有类型参数的 DSL 上,这会导致 GHC 出现模棱两可的类型参数错误。
为了澄清,这里有一些代码:
{-# 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 = _
正如 GHC 所暗示的那样,试图让它与启用AllowAmbiguousTypes扩展一起工作并没有让我更进一步。我尝试在类型签名中添加一些forall a风格的东西,但无济于事。
有什么办法可以让这种模式起作用吗?