说我有以下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)
我将如何构建这样的函数?
我尝试了不同的方法来绑定类型,但没有成功。 是否存在我缺少的扩展,可以实现更广泛的类型绑定?
这是错误消息:
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)
我想要完成的内容的描述: 我想设计一个DSL和一个函数运行,可以尝试以几种不同的方式运行DSL的一些代码(我为每种方式都有多个不同的运行函数)。 run函数将尝试运行尽可能多的代码,然后报告它无法运行的代码以及它可以运行的代码的结果。
答案 0 :(得分:7)
您需要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
。< / p>
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 :: Stage a b -> (a -> b)
run (a `Comb` b) = run b . run a
run (FMap f) = f