2012-03-30 61 views
5

以下等式是用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将是* - > *或任何东西 - >什么,我认为这是一个 - 在Haskell>一个

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

我不确定如何处理寻找rc和rh的类型。在rc中,g被部分应用于变量i - 所以我猜测这限制了我的类型[*]。 rc和g在rc的定义中应用了什么顺序? g是否应用于i,然后将得到的函数用作rc的参数?还是rc需要3个独立的v,g和i参数?我真的很困惑..任何帮助将不胜感激!多谢你们。

对不起忘了补充一点,HD是列表的标准头功能,并定义为:

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

这是功课吗? – 2012-03-30 13:07:53

+0

不,我现在正在准备考试,这是一个米兰达考试的老考试问题。 – user1058210 2012-03-30 13:11:42

+0

“hd”功能的类型是什么? – 2012-03-30 13:12:57

回答

6

类型是从什么是已知的类型和表现形式是如何在定义中使用的推断。

让我们开始在顶部,

rc v g i = g (v : i) 

所以rc :: a -> b -> c -> d,我们必须看看有什么可以发现关于a, b, cd。在右侧,出现(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,可能更多的信息有关ab如下。事实上,g []hd在RHS,所以g [] :: [c]g :: [a] -> [c]的说法,因此

rh :: ([a] -> [c]) -> c 

下一页

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

第一个参数是一个列表,如果是空的,结果是第二个参数,所以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] 
+0

谢谢丹尼尔!用第一个方程rc,我们将g应用于我们已经确定为类型[a]的i - 但是我们如何知道函数的输出是类型d?这不仅仅是rc的输出,也不一定是g的输出? – user1058210 2012-03-30 14:29:55

+0

我们对'rc'定义的'g'结果类型一无所知,所以无论传入参数'g'的结果类型是该调用中'rc'的结果类型。对于可以是任何类型的类型,我们使用类型变量,无论我们称之为“d”还是“simon”都不重要。在这里,我们不能称之为'a',因为这已经被用于另一种类型(但是传递'g1 :: [b] - > b'是合法的,'d'类型可能等于'a' ,但它不需要,因此得到不同的外延)。我留下了'd',因为这就是'rc'类型的第一个近似值的结果类型。 – 2012-03-30 14:36:22

+0

如果rc的结果只是另一个g函数,为什么rc的输出没有给出[a] - > d?整件事: rc :: a - >([a] - > d) - > [a] - >([a] - > d) – user1058210 2012-03-30 14:58:07

6

我要使用Haskell语法来写的类型。

rc v g i = g (v:i) 

这里rc有三个参数,所以它的类型将会像a -> b -> c -> dv:i必须是与vi相同类型的元素列表,因此v :: ai :: [a]g应用于该列表,以便g :: [a] -> d。 如果你把所有的东西放在一起,你会得到rc :: a -> ([a] -> d) -> [a] -> d

正如你已经想出rn :: a -> a,因为它只是身份。

我不知道您在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。 在第二种情况下通知如何xy在输入给予rcy必须是一个函数[a'] -> d,和rc x y :: a' -> d(即必须也y的类型,因为它是作为它的f秒参数传递)。 最后,我们可以说f :: [a'] -> ([a'] -> d) -> ([a'] -> d)。由于->是正确关联的,因此相当于[a'] -> ([a'] -> d) -> [a'] -> d

你可以用同样的方式推理其余的。

+0

'hd'来自Miranda标准库。它相当于Haskell中的'head',所以它的类型是'[a] - > a''。 – hammar 2012-03-30 14:15:51

+0

谢谢Riccardo!你能否看看我问过丹尼尔的问题,因为它也适用于你的答案 - 谢谢! – user1058210 2012-03-30 14:31:52

+0

高兴。对不起,我迟到了。他已经解释过你:) – 2012-03-30 15:13:45