Types 函数式编程中函数类型的确定

Types 函数式编程中函数类型的确定,types,definition,Types,Definition,以下公式是用Miranda语法编写的,但由于Miranda和Haskell之间的相似性,我希望Haskell程序员应该理解它 如果定义以下函数: rc v g i = g (v:i) rn x = x rh g = hd (g []) f [] y = y f (x:xs) y = f xs (rc x y) g [] y = y g (x:xs) y = g xs (x:y) 你如何计算函数的类型?我想我知道如何计算f,g和rn,但我对部分应用部分感到困惑 rn将是*->*(或者任何

以下公式是用Miranda语法编写的,但由于Miranda和Haskell之间的相似性,我希望Haskell程序员应该理解它

如果定义以下函数:

rc v g i = g (v:i)
rn x = x
rh g = hd (g [])


f [] y = y 
f (x:xs) y = f xs (rc x y)

g [] y = y
g (x:xs) y = g xs (x:y)
你如何计算函数的类型?我想我知道如何计算f,g和rn,但我对部分应用部分感到困惑

rn将是*->*(或者任何东西->任何东西,我认为它是哈斯凯尔的a->a?)

对于f和g,函数类型是否都是[*]->*->*->*

我不确定如何找到rc和rh的类型。在rc中,g部分地应用于变量i,所以我猜这会将i的类型限制为[*]。在定义rc时,rc和g的顺序是什么?g是否应用于i,然后结果函数用作rc的参数?或者rc是采用v、g和i这三个单独的参数?我真的很困惑。。任何帮助都将不胜感激!谢谢各位

抱歉,忘记添加hd是列表的标准头函数,定义如下:

hd :: [*] -> *
hd (a:x) = a
hd [] = error "hd []"

根据已知的类型以及表达式在定义中的使用方式推断类型

让我们从顶部开始

rc v g i = g (v : i)
所以
rc::a->b->c->d
,我们必须看看关于
a,b,c
d
可以找到什么。在右侧,出现了
(v:i)
,因此使用
v::a
,我们可以看到
i:[a]
c=[a]
。然后
g
应用于
v:i
,因此
g::[a]->d

rc :: a -> ([a] -> d) -> [a] -> d
rn x=x
意味着
rn
的参数类型没有约束,其返回类型相同,
rn::a->a

rh g = hd (g [])
由于
rh
的参数
g
应用于RHS上的空列表,因此它必须具有类型
[a]->b
,下面可能有关于
a
b
的更多信息。实际上,
g[]
是RHS上的
hd
的参数,因此
g[]:[c]
g:[a]->[c]
,因此

rh :: ([a] -> [c]) -> c
下一个

第一个参数是一个列表,如果该列表为空,则结果是第二个参数,因此
f::[a]->b->b
遵循第一个等式。现在,在第二个等式中,在RHS上,
f
的第二个参数是
rc x y
,因此
rc x y
必须具有与
y
相同的类型,我们称之为
b
。但是

rc :: a -> ([a] -> d) -> [a] -> d
,因此
b=[a]>d
。因此

f :: [a] -> ([a] -> d) -> [a] -> d
最后

g [] y = y
g (x:xs) y = g xs (x:y)
我们从第一个方程推导出
g::[a]->b->b
。从第二个开始,我们推导出
b=[a]
,因为我们取
g
的第一个参数的头部,并将其与第二个相反,因此

g :: [a] -> [a] -> [a]

我将使用haskell语法来编写类型

rc v g i = g (v:i)
这里,
rc
接受三个参数,所以它的类型类似于
a->b->c->d
v:i
必须是与
v
i
类型相同的元素列表,因此
v::a
i:[a]
g
应用于该列表,因此
g::[a]>d
。 如果把所有这些放在一起,就会得到
rc::a->([a]->d)->[a]->d

正如您已经计算出的那样,因为它只是身份

我不知道您在
rh
中使用的
hd
函数的类型,所以我将跳过它

f [] y = y 
f (x:xs) y = f xs (rc x y)
这里的
f
接受两个参数,因此其类型类似于
a->b->c
。 从第一种情况,我们可以推断
b==c
,因为我们返回
y
,并且第一个参数是一个列表。 现在我们知道
f::[a']->b->b
。 在第二种情况下,请注意在
rc
的输入中如何给出
x
y
y
必须是一个函数
[a']->d
rc x y::a'->d
(这也必须是
y
的类型,因为它是作为
f
的第二个参数传递的)。 最后,我们可以说
f::[a']->([a']->d)->([a']->d)
。由于
->
是右关联的,因此这相当于
[a']->([a']->d)->[a']->d


你可以用同样的方式对剩下的部分进行推理。

不,我现在正在准备考试,这是Miranda考试的一个旧试题。
hd
函数的类型是什么?抱歉,忘了添加该定义-我现在已经将它添加到了问题中
hd
来自Miranda标准库。它相当于Haskell中的
head
,因此它的类型是
[a]->a
。谢谢Riccardo!你能看看我问丹尼尔的问题吗,因为它也适用于你的答案-谢谢!很高兴。对不起,我迟到了。他已经向你解释过了:)谢谢丹尼尔!对于第一个方程rc,我们将g应用于i,我们已经确定为类型[a]——但是我们如何知道函数的输出是类型d?这不仅仅是rc的输出,不一定也是g的输出吗?我们从
rc
的定义中不知道
g
的结果类型,所以无论传递的参数
g
的结果类型是什么,都是该调用中
rc
的结果类型。对于可以是任何类型的类型,我们使用类型变量,无论我们称之为
d
还是
simon
,都无关紧要。在这里,我们不能称它为
a
,因为它已经用于另一个类型(但是传递a
g1::[b]->b是合法的,类型
d
可能等于
a
,但它不需要,因此它得到不同的表示)。我留下了
d
,因为这是
rc
类型的第一个近似结果类型。如果rc的结果只是另一个g函数,为什么rc的输出不是作为[a]>
f [] y = y 
f (x:xs) y = f xs (rc x y)