2012-02-24 74 views
4

我已经看到了几个在参数中使用函数的Haskell代码的例子,但我永远无法让它为我工作。是否可以在Haskell参数中使用函数?

例如:

-- Compute the nth number of the Fibonacci Sequence 
    fib 0 = 1 
    fib 1 = 1 
    fib (n + 2) = fib (n + 1) + fib n 

当我尝试这一点,我得到这个错误:

Parse error in pattern: n + 2 

这只是一个坏榜样?或者我必须做一些特殊的事情来完成这项工作?

+0

也许这是有趣的? http://stackoverflow.com/questions/3748592/what-are-nk-patterns-and-why-are-they-banned-from-haskell-2010 – gspr 2012-02-24 15:50:42

+3

这些所谓的(n + k)模式从Haskell被禁止前一段时间。将第三行替换为:'fib n = fib(n - 1)+ fib(n - 2)'。 – Vitus 2012-02-24 15:51:22

+0

注意:还有一种方法可以在等式左侧看到函数调用:[ViewPatterns](http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns)。我很惊讶他们不是更常见。 – 2012-02-24 17:28:59

回答

1

由于(+)是一个函数,因此无法对它进行模式匹配。要做你想做的事,你需要修改第三行:fib n = fib (n - 1) + fib (n - 2)

2

我会尽力帮忙,是一个总的新手在Haskell。

我认为问题在于你无法匹配(n + 2)。 从逻辑的角度来看,任何参数“n”都不会匹配“n + 2”,所以你的第三条规则永远不会被选中进行评估。

您可以重写它,就像迈克尔说,:

fib n = fib (n - 1) + fib (n - 2) 

或使用警卫定义一个函数整个fibonnaci,是这样的:

fibonacci :: Integer -> Integer 
fibonacci n 
| n == 0 = 0 
| (n == 1 || n == 2) = 1 
| otherwise = fibonacci(n-1) + fibonacci(n-2)  
+0

我认为你的意思是*警卫*,而不是你最后一个例子中的模式匹配。 – gspr 2012-02-24 15:56:56

+0

的确,我的确像我说的...一个新手一样,最终我滥用了这种语言。谢谢。 – pcalcao 2012-02-24 15:58:02

2

模式匹配器,仅限于构造函数。因此,尽管可以匹配(:)(列表constrcutor)或LeftRight(构造函数Either)等函数的参数,但不能匹配算术表达式。

2

我认为fib (n+2) = ...表示法不起作用,是一个语法错误。您可以使用“正则表达式”的风格匹配的paramters,如列表或元组:

foo (x:xs) = ... 

其中x是列表的头部和XS的列表的其余部分或

foo (x:[]) = 

其匹配如果列表只剩下一个元素并存储在x中。即使是复杂的匹配,如

foo ((n,(x:xs)):rg) = ... 

是可能的。 haskell中的函数定义是一个复杂的主题,可以使用很多不同的样式。

另一种可能性是使用“切换情况下的”方案的:

foo f x | (f x) = [x] 
foo _ _ = [] 

在这种情况下,元素“X”被包裹在一个列表中,如果条件(f x)是真实的。在其他情况下,f和x参数不感兴趣,并返回一个空列表。

解决您的问题,我不认为任何一个都适用,但为什么不以追赶其余参数值函数定义抛出,如:

fib n = (fib (n - 1)) + (fib (n - 2)) 

希望这有助于,

奥利弗

3

正如托马斯所说,你可以使用视图模式来实现:

{-# LANGUAGE ViewPatterns #-} 

fib 0 = 1 
fib 1 = 1 
fib ((subtract 2) -> n) = fib (n + 1) + fib n 

由于在这种情况下-含糊不清,您需要改用subtract函数。