Types 函数式编程中函数类型的确定
以下公式是用Miranda语法编写的,但由于Miranda和Haskell之间的相似性,我希望Haskell程序员应该理解它 如果定义以下函数: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将是*->*(或者任何
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
,因为它已经用于另一个类型(但是传递ag1::[b]->b是合法的,类型d
可能等于a
,但它不需要,因此它得到不同的表示)。我留下了d
,因为这是rc
类型的第一个近似结果类型。如果rc的结果只是另一个g函数,为什么rc的输出不是作为[a]>
f [] y = y
f (x:xs) y = f xs (rc x y)