下面的等式是用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,但我对部分应用程序部分感到困惑。
将会是* - > * (或其他任何内容 - >任何内容,我认为它是 - > Haskell中的&a; )
对于f和g,函数类型 [*] - > * - > *
我不确定如何找到rc和rh的类型。在rc中,g被部分地应用于变量i - 所以我猜这会将i的类型约束为[*]。 rc和g在rc的定义中应用了什么顺序?是否将g应用于i,然后将结果函数用作rc的参数?或者rc是否采用v,g和i的3个独立参数?我真的很困惑..任何帮助将不胜感激!谢谢你们。
抱歉忘了添加hd是列表的标准head函数,定义为:
hd :: [*] -> *
hd (a:x) = a
hd [] = error "hd []"
答案 0 :(得分:6)
从已知的类型以及定义中如何使用表达式推断出类型。
让我们从顶部开始,
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
完全适用于<{p}}
rc :: a -> ([a] -> d) -> [a] -> d
rn x = x
表示rn
的参数类型没有约束,其返回类型相同,rn :: a -> a
。
rh g = hd (g [])
由于rh
的参数g
已应用于RHS上的空列表,因此它必须包含[a] -> b
类型,可能有关a
或{{1}的更多信息跟随。实际上,b
是RHS上g []
的参数,因此hd
和g [] :: [c]
,因此
g :: [a] -> [c]
下一步
rh :: ([a] -> [c]) -> c
第一个参数是一个列表,如果是空的,则结果是第二个参数,因此f [] y = y
f (x:xs) y = f xs (rc x y)
跟随第一个等式。现在,在第二个等式中,在RHS上,f :: [a] -> b -> b
的第二个参数是f
,因此rc x y
必须与rc x y
具有相同的类型,我们称之为y
1}}。但
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
答案 1 :(得分:6)
我将使用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
。
正如您已经发现rn :: a -> a
,因为它只是身份。
我不知道您在hd
中使用的rh
函数的类型,所以我会跳过它。
f [] y = y
f (x:xs) y = f xs (rc x y)
此处f
有两个参数,因此其类型类似于a -> b -> c
。
从第一种情况开始,我们可以推导出b == c
,因为我们返回y
,并且第一个参数是一个列表。
现在我们知道f :: [a'] -> b -> b
。
在第二种情况下,请注意x
的输入中y
和rc
是如何给出的:y
必须是函数[a'] -> d
和rc x y :: a' -> d
(它必须也是y
的类型,因为它作为f
的第二个参数传递。
最后,我们可以说f :: [a'] -> ([a'] -> d) -> ([a'] -> d)
。由于->
是右关联的,因此相当于[a'] -> ([a'] -> d) -> [a'] -> d
。
你可以用同样的方式推断其余的。