学习haskell:创建skip Bigram的递归函数

学习haskell:创建skip Bigram的递归函数,haskell,recursion,Haskell,Recursion,我正在努力完成,我正在读关于递归函数的章节。用于计算bigram的递归函数如下所示: bigram :: [a] -> [[a]] bigram [] = [] bigram [_] = [] bigram xs = take 2 xs : bigram (tail xs) 如果我在wordlist=[“无色”、“绿色”、“创意”、“睡眠”、“狂暴”]上运行它,我会得到: bigram chomsky [("colorless","green"

我正在努力完成,我正在读关于递归函数的章节。用于计算bigram的递归函数如下所示:

bigram :: [a] -> [[a]]
bigram [] = [] 
bigram [_] = []
bigram xs = take 2 xs : bigram (tail xs)
如果我在
wordlist=[“无色”、“绿色”、“创意”、“睡眠”、“狂暴”]
上运行它,我会得到:

bigram chomsky

[("colorless","green"),("green","ideas"),("ideas","sleep"),("sleep","furiously")]
演习说:

跳过二元图是按句子顺序排列的任何一对单词。编写一个函数skipBigrams,使用显式递归从句子中提取skip bigrams作为二进制元组列表。在
[“无色”、“绿色”、“创意”、“睡眠”、“狂暴”]
上运行函数时,应给出以下输出:

Prelude>skipBigrams[“无色”、“绿色”、“创意”、“睡眠”、“狂暴”]
[(“无色”、“绿色”)、(“无色”、“想法”)、(“无色”、“睡眠”)、(“无色”、“狂暴”)、(“绿色”、“想法”)、(“绿色”、“狂暴”)、(“想法”、“睡眠”)、(“想法”、“狂暴”)、(“睡眠”、“狂暴”)]

以下是我尝试过的定义:

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)
这对哈斯克尔来说,虽然我是新手,但我一点也不懂。什么是无限型?相关的约束

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

skipBigram::[a]->[(a,a)]
skipBigram[]=[]--与空列表无关

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

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

这就是错误告诉你的


以下是一些细节:

看看你的最后一行

skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]
右侧有一个元组列表,因此其类型如下(基于结果列表的第一个元素):

但是在第二项中有
(x,skipBigram xs)
意味着它将有
(a,[(a,a)])
(记住
skipBigram xs的类型是上面的部分)

因此-比较元组的第二部分-你有
a~[(a,a)]
,它会产生你的错误,因为某种程度上
a
类型应该与
[(a,a)]
相同,你可以永远展开它;)


现在谈谈算法本身:

它不会像这样工作-你必须以某种方式获得所有的组合,要做到这一点,你必须处理列表中的项目

通常,您可以使用列表理解或列表单子的do符号来执行此操作

要开始思考这个问题:

f [] = [[]]
f (x:xs) =
  let xss = f xs
  in [ x:xs | xs <- xss ] ++ xss
f[]=[]]
f(x:xs)=
设xss=fxs

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

但是,即使忽略类型错误,您的函数也不会执行您想要的操作。首先,您的函数将始终返回长度为2的列表,因为您已显式构造了该列表。此外,结果将包括
(“无色”、“无色”)
,因为
(x,head xs)
(x,x)相同

相反,试试这个解决方案

skipBigram :: [a] -> [(a, a)]
skipBigram [] = []
skipBigram (x:xs) = map (x,) xs ++ skipBigram xs
要使此函数正常工作,您需要将

{-# LANGUAGE TupleSections #-}

在文件的开头。

@Jono查看列表理解的引用您可以省略单件案例-x:xs案例正确地覆盖了它。
skipBigram(x:xs)=map(x,)xs
不会进行任何递归调用…因此它不会生成所需的结果list@recursion.ninja我非常清楚这一点(我在发布之前测试了我的代码片段)…想法是让他自己试验并解决问题;)(如果你理解了我给你的代码片段,你应该能够理解/写所有类型的组合材料…)我理解你的教学方法。我想知道@Jono是否能通过比较我们的答案来理解为什么它计算得太多……这可能是一个很好的练习!
skipBigram :: [a] -> [(a, a)]
skipBigram [] = []
skipBigram (x:xs) = map (x,) xs ++ skipBigram xs
{-# LANGUAGE TupleSections #-}