试图让我的头脑(x:xs)和列表?

时间:2011-05-03 20:07:49

标签: list haskell syntax recursion

我一直受到列表工作方式的挑战,并对整个(x:xs)概念感到困惑。我似乎并没有理解它。

实施例

select :: Ord a => a -> [a] -> [a]
select y [] = []
select y (x:xs)
    | x < y     = x : select y xs
    | otherwise = select y xs

P.S。我确切地知道函数的作用,但任何人都能够解释这个过程(特别是奇怪的Ord a=>符号)?

非常感谢任何有效的策略。

提前致谢。伊恩。

3 个答案:

答案 0 :(得分:9)

确定。让我们来看看这里不同的句法元素。

第1行

select :: Ord a => a -> [a] -> [a]

这是一种类型声明。它是函数的声明(因为它有->种类型)。

该函数有两个参数。

  • 第一个是任何类型的单个值,由a表示(小写表示它是多态类型)。
  • 第二个参数是与第一个参数相同的任何类型的列表。

返回值是任何类型的列表,与参数类型相同。

Ord a组件是类型类约束,它表示给出此函数的任何类型也必须是Ord类的实例。这是一类可以比较的类型。

第2行

现在我们来看第2行:

select y [] = []

这是select函数本身的一个定义。它非常简单,包含两个参数的模式,以及结果的规范。它写着:

  

如果第一个参数是任何值(我们将命名为y),第二个参数是空列表(由[]模式表示),则select计算为空列表。

第3行

第3行包含列表的另一种情况:

select y (x:xs)

同样,这是select函数定义的一部分,对于第二个参数是空列表的情况。如果它不是空列表,那么它是一个头部x和尾部xs的列表。 “cons”构造函数(:)组合了列表头部和尾部。这也是我们如何在列表上进行模式匹配,以提取头部和尾部。

通过列表的头部和尾部的模式匹配,使用(x:xs),我们将新变量x绑定到列表头部的值,并xs到列表尾部的值。

第4和第5行

最后两行是额外的 guards ,如果第二个参数是非空列表,则根据其他检查进行测试和分支:

| x < y     = x : select y xs
| otherwise = select y xs

x小于第一个参数y时,第一个警卫会触发。如果是这样,我们会返回一个新的列表,其中x位于头部,select再次应用于尾部。

如果不是这样,那么我们从列表中删除x,并仅返回递归调用tail时发生的情况。


有关Haskell如何工作的更多信息,我建议使用介绍性文本,例如:

值得你花时间。

答案 1 :(得分:2)

我的Haskell充其量只是限制,但我会给出我能得到的答案,以防其他人没有...

select :: Ord a => a -> [a] -> [a]

这说:

  

select函数使用任何类型“a”,使得该类型属于类型“Ord”(Orderable)。它需要一个类型的实例加上类型列表并返回一个列表   类型。

如果有帮助,在Java中这可能表示为(kindof):

<T implements Comparable> List<T> select(T value, List<T> listOfValues);

实际的功能定义说:

  • 如果传入空列表,则返回空列表,否则返回
  • 如果传入的列表的第一个元素小于该值,则返回一个列表,该列表由附加到列表中的元素组成,该元素是通过评估应用于列表其余部分的函数得出的,否则
  • 返回一个列表,该列表由附加到列表中的元素组成,该元素是通过评估函数得出的(即,没有第一个元素)

编辑:在上述上下文中可订购意味着“您可以将该类型的值相互比较以确定哪个'先来''”。即,&lt;,=和&gt;运算符是为类型的值定义的。 “Ord”是一个由(实际上)Haskell标准库定义的TypeClass(Prelude?我忘了它叫什么)

答案 2 :(得分:1)

(x:xs)用于对缺点单元格进行模式匹配。当你说[1,2,3]时,它实际上是1:(2:(3:[]))的语法糖。因此,当select 1 [1,2,3]被调用时:

select y []     = ... -- pattern skipped; [1,2,3] does not match []
select y (x:xs) = ... -- pattern used, with y = 1, x = 1, and xs = [2,3]

因此,在(x:xs)中,x是列表中的第一项,xs是剩余项目。只有列表不为空时,此模式才会匹配。

对于Ord a =>语法,它表示“如果a是类型类Ord的实例”。 Int会在这里工作,因为它有Ord的实例,可能如下所示:

instance Ord Int where
    (<=) = primitiveIntLessThanOrEqual

如果您离开Ord a并刚刚说select :: a -> [a] -> [a],那么x < y将无效,因为它需要类Ord中类型的参数:

(<) :: (Ord a) => a -> a -> Bool