学习haskell:用于创建skip-bigrams的递归函数

时间:2015-08-19 17:58:36

标签: haskell recursion

我正在通过NLPWP Book工作,我在处理递归函数的章节中。计算双字母组合的递归函数如下所示:

bigram :: [a] -> [[a]]
bigram [] = [] 
bigram [_] = []
bigram xs = take 2 xs : bigram (tail xs)

如果我在wordlist = ["colorless", "green", "ideas", "sleep", "furiously"]上运行它,我会得到这个:

bigram chomsky

[("colorless","green"),("green","ideas"),("ideas","sleep"),("sleep","furiously")]

练习说:

  

skip-bigram是句子顺序中的任意一对单词。编写一个函数skipBigrams,使用显式递归从句子中提取skip-bigrams作为二进制元组列表。在["Colorless", "green", "ideas", "sleep", "furiously"]上运行您的函数应该提供以下输出:

     

Prelude> skipBigrams ["Colorless", "green", "ideas", "sleep", "furiously"]   [("Colorless","green"),("Colorless","ideas"),("Colorless","sleep"),("Colorless","furiously"),("green","ideas"),("green","sleep"),("green","furiously"),("ideas","sleep"),("ideas","furiously"),("sleep","furiously")]

以下是我尝试过的定义:

skipBigram [] = [] 
skipBigram [_] = []
skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]

但我收到以下错误:

Occurs check: cannot construct the infinite type: t ~ [(t, t)]
Relevant bindings include
  xs :: [t] (bound at :3:15)
  x :: t (bound at :3:13)
  skipBigram :: [t] -> [(t, t)] (bound at :1:1)
In the expression: interactive:IHaskell384.skipBigram xs
In the expression: (x, interactive:IHaskell384.skipBigram xs)

对我来说,Haskell很新,我一点也不明白。什么是无限类型?一个相关的约束?

我应该如何定义 skipBigram 来解决此编译时错误?

3 个答案:

答案 0 :(得分:2)

你得到这个是因为你的结果是一对列表,其中该列表中第一项的第二部分是某个元素而结果列表中第二项的第二部分是,无论你是什么试图回馈(你在这里使用递归,所以它将具有相同的类型) - 所以你说:

  

我的结果是一个元组列表,但这些元组的一部分是结果类型本身

错误告诉你的是

这里有一些细节:

看看你的最后一行

skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]

你有一个右侧的元组列表,所以它的类型就像(基于结果列表的第一个元素):

skipBigram :: [a] -> [(a,a)]

但是在第二项中,(x, skipBigram xs)表示其类型为(a, [(a,a)])(请记住skipBigram xs的类型是上述部分)。

所以 - 比较元组的第二部分 - 你有a ~ [(a,a)]产生错误,因为某种类型a应该与[(a,a)]相同,你可以扩展所有类型f [] = [[]] f (x:xs) = let xss = f xs in [ x:xs | xs <- xss ] ++ xss 永恒;)

现在算法本身:

它不会像这样工作 - 你必须得到所有组合并且要做到这一点你必须使用列表中的项目。

通常你可以使用list-comprehensions或list-monad的do-notation来执行此操作。

要开始思考:

.contentmenubutton:hover{
text-decoration: none;

测试它并在ghci中玩它 - 你必须将它与你得到的东西结合起来

(好的recursion.ninja ^^破坏了你的乐趣 - 如果你不介意的话,我会把它放在这里)

答案 1 :(得分:1)

Try this definition:

skipBigram :: [a] -> [(a,a)]
skipBigram     [] = [] -- nothing to do with an empty list
skipBigram (x:xs) = [(x,y) | y <- xs] ++ skipBigram xs

您的skipBigram函数正在生成列表中所有单词的“2元组从左到右组合”。我们可以在递归定义中使用simple list comprehension捕获此概念。通过递归连接简单列表推导,我们获得了所需的结果列表。

答案 2 :(得分:1)

无限类型错误抱怨您使用列表。您的函数应该具有类型[a] -> [a] -> [(a, a)],但是当GHC尝试推断您的函数类型时,它会获得a = [a],这是一种无限类型。相关绑定只是可能导致错误的其他变量的类型。

但是,即使忽略类型错误,您的功能也根本无法实现。首先,您的函数将始终返回长度为2的列表,因为您已明确构造了列表。此外,结果还包括("Colorless", "Colorless"),因为此处(x, head xs)(x, x)相同。

相反,请尝试此解决方案

skipBigram :: [a] -> [(a, a)]
skipBigram [] = []
skipBigram (x:xs) = map (x,) xs ++ skipBigram xs

要使此功能起作用,您需要设置

{-# LANGUAGE TupleSections #-}

在文件的开头。