当这些约束成立时,将没有约束的GADT转换为具有约束的另一个GADT

时间:2013-03-30 10:25:54

标签: haskell dsl gadt

我们可以将没有给定约束的GADT转换为具有上述约束的GADT吗?我想这样做是因为我希望深入嵌入箭头并使用表示(现在)似乎需要Typeable来做一些有趣的事情。 (One reason

data DSL a b where
  Id   :: DSL a a
  Comp :: DSL b c -> DSL a b -> DSL a c
  -- Other constructors for Arrow(Loop,Apply,etc)

data DSL2 a b where
  Id2   :: (Typeable a, Typeable b)             => DSL2 a a
  Comp2 :: (Typeable a, Typeable b, Typeable c) => DSL2 b c -> DSL2 a b -> DSL2 a c
  -- ...

我们可以尝试以下from功能,但由于我们没有这个功能,因此很快就会崩溃 Typeable递归点的信息

from :: (Typeable a, Typeable b) =>  DSL a b -> DSL2 a b
from (Id)       = Id2
from (Comp g f) = Comp2 (from g) (from f)

因此我们尝试捕获类型类中的转换。但是,由于Typeable b是一个存在主义,因此我们将错过b信息,这将会中断。

class From a b where
  from :: a -> b

instance (Typeable a, Typeable b) => From (DSL a b) (DSL2 a b) where
  from (Id)       = Id2
  from (Comp g f) = Comp2 (from g) (from f)

还有其他建议吗?最后,我想要创建CategoryArrow的深度嵌入以及有关类型参数的Typeable信息。这样我就可以使用arrow-syntax在我的DSL中构造一个值,并拥有相当标准的Haskell代码。也许我不得不求助于模板Haskell?

2 个答案:

答案 0 :(得分:15)

递归案例的问题对于将DSL a b转换为DSL2 a b至关重要。

要进行此转换,需要在Typeable案例中找到存在类型b的{​​{1}}字典 - 但Comp实际上已被遗忘。< / p>

例如,请考虑以下程序:

b

换句话说,如果有一种方法可以进行一般的转换,你可以某种方式为一个实际上没有一个的类型发明一个data X = X Int -- No Typeable instance for X dsl1 :: DSL X Char dsl1 = -- DSL needs to have some way to make non-identity terms, -- use whatever mechanism it offers for this. dsl2 :: DSL Int X dsl2 = -- DSL needs to have some way to make non-identity terms, -- use whatever mechanism it offers for this. v :: DSL Int Char v = Comp dsl1 dsl2 v2 :: DSL2 Int Char v2 = -- made by converting v from DSL to DSL2, note that Int and Char are Typeable typeOfIntermediate :: DSL a c -> TypeRep typeOfIntermediate int = case int of Comp (bc :: DSL2 b c) (ab :: DSL2 a b) -> typeOf (undefined :: b) typeOfX = typeOfIntermediate v2 实例。

答案 1 :(得分:3)

  

最终,我想要创建CategoryArrow的深度嵌入以及有关类型参数的Typeable信息。这样我就可以使用arrow-syntax在我的DSL中构造一个值,并且具有相当标准的Haskell代码。

也许你应该诉诸{-# LANGUAGE RebindableSyntax #-}(同时注意到它意味着NoImplicitPrelude)。创建您自己的arr(>>>)firstapp(|||)loop函数,GHC将在使用箭头符号时使用它们,而不是Control.Arrow的标准版本。

手册指出“这些函数的类型必须非常接近地匹配Prelude类型”。如果您正在构建并行类层次结构(Control.Arrow中的层次结构的副本,但在类型签名中添加了Typeable约束),那么您应该没问题。

(n.b。我对箭头符号并不熟悉所以从来没有将它与RebindableSyntax结合使用;我的答案是一个聪明的猜测。)