Haskell 无法析构函数传递类型

Haskell 无法析构函数传递类型,haskell,gadt,Haskell,Gadt,假设我有以下GADT: data Stage a b where Comb :: Stage a b -> Stage b c -> Stage a c FMap :: (a -> b) -> Stage a b 我现在想要一个这样工作的函数: run (a `Comb` b) = (a,b) run (FMap f) = (FMap f,FMap id) run :: Stage a b -> (a -> b) run (a `C

假设我有以下GADT:

data Stage a b where
    Comb :: Stage a b -> Stage b c -> Stage a c
    FMap :: (a -> b) -> Stage a b
我现在想要一个这样工作的函数:

run (a `Comb` b) = (a,b)
run (FMap f)     = (FMap f,FMap id)
run :: Stage a b -> (a -> b)
run (a `Comb` b) = run b . run a
run (FMap f)     = f
我将如何构造这样一个函数

我尝试了不同的绑定类型的方法,但没有成功。 是否有我缺少的扩展支持更广泛的类型绑定

这是错误消息:

Couldn't match type `t' with `(Stage t1 b, Stage b t2)'
  `t' is a rigid type variable bound by
      the inferred type of run :: Stage t1 t2 -> t at <interactive>:11:5
In the expression: (a, b)
In an equation for `run': run (a Comb b) = (a, b)
无法将类型“t”与“(阶段t1 b,阶段b t2)”匹配
`t'是一个刚性类型变量,由
运行的推断类型::阶段t1 t2->t at:11:5
在表达式中:(a,b)
在“运行”的方程式中:运行(a梳b)=(a,b)
描述我想要完成的任务: 我想设计一个DSL和一个函数运行,可以尝试以两种不同的方式运行DSL的一些代码(每种方式我有多个不同的运行函数)。
run函数将尝试运行给定的尽可能多的代码,然后报告它无法运行的代码以及它可以运行的代码的结果。

您需要运行
的类型签名,因为您在GADT上进行模式匹配。GADT上的模式匹配需要类型细化,通常只有在存在类型签名的情况下才有效

但目前尚不清楚签名的类型。如果输入值为

a `Comb` b :: Stage x y
然后返回
(a,b)
,其中

a :: Stage x b
b :: Stage b y
对于一些未知的
b
。这是一种存在类型转义。您不能写入

run :: Stage x y -> (State x b, Stage b y)
因为这意味着它必须适用于所有
b
,但它只适用于某些(未知)
b

不幸的是,不清楚为什么要编写像
run
这样的函数。为什么要生产一双呢?你以后想用这双鞋做什么?
Comb
构造函数被定义为组合具有未知中间类型的两个阶段,因此此版本的
run
可以工作:

run :: Stage a b -> Stage a b
run (a `Comb` b) = a `Comb` b
run (FMap f)     = FMap f `Comb` FMap id
或者,您可以定义一个更具体的数据类型,只允许两个阶段的“对”具有未知的中间类型:

data PairStages a b where
  PairStages :: Stage a b -> Stage b c -> PairStages a c
然后:

run :: Stage a b -> PairStages a b
run (a `Comb` b) = PairStages a b
run (FMap f)     = PairStages (FMap f) (FMap id)
但我仍然觉得奇怪,
run
返回了一对。正如我所说的,不清楚您希望如何处理
run
的结果。让
run
成为一个递归函数似乎更有用,它实际上以某种方式组合了
Comb
案例中运行组件的结果。例如,像这样:

run (a `Comb` b) = (a,b)
run (FMap f)     = (FMap f,FMap id)
run :: Stage a b -> (a -> b)
run (a `Comb` b) = run b . run a
run (FMap f)     = f

您需要运行
的类型签名
,因为您在GADT上进行模式匹配。另外,如果您返回
(a,b)
,您有一个存在类型转义,因此这无法工作。@kosmikus请将其添加为答案。@dave4420我希望这会提示更多细节,以便我可以给出一个真正的答案。但是好吧…@kosmikus如果我添加一个类型签名,我似乎遇到的问题是它不能统一
Comb
的类型和函数类型。好吧,那就不可能了?是否可以使用存在限定符?是否可以改为使用
b
?怎么做?@nulvinge是的,这是不可能的,因为你似乎想这样做。您可以再次创建存在主义,但这正是
Comb
构造函数所做的。我想你必须说出你真正想做什么,以及为什么要定义
run
,正如给定的那样…我更新了问题,并描述了我正在尝试做什么。@nulvinge我也更新了答案。不幸的是,你添加的信息并没有真正的帮助。我不清楚为什么要用您描述的方式定义
运行
。尽管如此,我还是做了一些推测,并提出了一些可能对你有用的选择。