(co)递归定义如何在Haskell中工作?

时间:2015-07-27 14:48:36

标签: haskell recursion declaration corecursion

我正在玩这种语言开始学习,而且我对于递归定义的工作原理感到困惑。

例如,让我们采用三角数的序列(TN n = sum [1..n]

提供的解决方案是:

triangularNumbers = scanl1 (+) [1..]

到目前为止,非常好。

但我提出的解决方案是:

triangularNumbers = zipWith (+) [1..] $ 0 : triangularNumbers

这也是正确的。

现在我的问题是:这如何转化为较低级别的实施?当满足这样的递归定义时,场景背后会发生什么?

1 个答案:

答案 0 :(得分:5)

这是一个简单的递归函数,它为您提供第n个三角形数字:

tweets=[]
user_input=input('Tweets to be labeled:')

readdata=csv.reader(open(user_input,'r'))
for row in readdata:
    tweets.append(row)
Header = tweets[0]
tweets.pop(0)
Academic_test_tweets=tweets[:]
Tweets=[]
for (words) in tweets:
    bigram=[]
    bigram_list=[]
    words_filtered = [e.lower() for e in WordPunctTokenizer().tokenize(words) if len(e) >= 3]
    words_filtered=[re.sub(r'(.)\1+', r'\1\1', e) for e in words_filtered if len(e)>=3]
    bigram_words=bigrams(words_filtered)
    for x in bigram_words:
        bigram.append(x)
    for (bi) in bigram:
        bigram_word=bi[0]+bi[1]
        bigram_list.append(bigram_word)
    list_to_append=words_filtered+bigram_list
    Tweets.append(list_to_append)
Academic_test_tweets_words=Tweets[:]

您的解决方案triag 0 = 0 triag n = n + triag (n-1) 更有趣:它是 corecursive clickclick)。在给定初始段的情况下,通过递归地指定下一个值来定义整个无限三角数序列,而不是通过将第n个数减少到较小输入的值来计算第n个数。

Haskell如何处理这样的核心运行?当它遇到您的定义时,实际上没有执行任何计算,它将被推迟到需要进一步计算的结果。当您访问列表triag' = zipWith (+) [1..] $ 0 : triag'的特定元素时,Haskell会根据定义开始计算列表的元素,直到访问的元素为止。有关详细信息,我发现有关惰性评估的this文章很有帮助。总之,除非您需要预测内存使用情况,否则延迟评估很有用。

Here是一个类似的SO问题,逐步解释了triag'的评估,这是Fibonacci序列的一个核心定义。