Haskell 无法析构函数传递类型
假设我有以下GADT: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
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我也更新了答案。不幸的是,你添加的信息并没有真正的帮助。我不清楚为什么要用您描述的方式定义运行。尽管如此,我还是做了一些推测,并提出了一些可能对你有用的选择。