繁体   English   中英

试图了解 (x:xs) 和列表?

[英]Trying to get my head around (x:xs) and lists?

我一直受到列表工作方式的挑战,并对整个 (x:xs) 概念感到困惑。 我只是似乎没有意识到这一点。

例子

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

PS 我确切地知道 function 做了什么,但是任何人都能够解释这个过程(尤其包括奇怪的Ord a=>符号)?

任何有效的策略将不胜感激。

提前致谢。 伊恩。

好的。 让我们在这里了解不同的句法元素。

1号线

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

这是一个类型声明。 它是 function 的声明(因为它具有->类型)。

function 有两个 arguments。

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

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

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

2号线

现在我们看第 2 行:

select y [] = []

这是select function 本身的一种定义。 它非常简单,包含两个 arguments 的模式和结果规范。 上面写着:

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

3号线

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

select y (x:xs)

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

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

第 4 行和第 5 行

如果第二个参数是非空列表,最后两行是基于额外检查进行测试和分支的额外守卫

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

x小于第一个参数y时,第一个守卫会触发。 如果是这样,我们返回一个带有x在头部的新列表,并且select再次应用于尾部。

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


有关 Haskell 工作原理的更多信息,我推荐介绍性文本,例如:

这将是值得您花时间的。

我的 Haskell 充其量是有限的,但我会给出我能给出的答案,以防其他人这样做......

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

这说:

select function 使用任何类型“a”,以便该类型属于类型类“Ord”(可订购)。 它接受一个类型的实例加上一个类型的列表并返回一个类型的列表。

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

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

实际的 function 定义说:

  • 如果传入一个空列表,则返回一个空列表,否则
  • 如果传入的列表的第一个元素小于该值,则返回一个列表,该列表包含附加到列表的该元素,该列表是通过评估应用于列表的 rest 的 function 产生的,否则
  • 返回一个列表,该列表由附加到评估 function 产生的列表中的元素组成(即,没有第一个元素)

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

(x:xs)用于对 cons 单元格进行模式匹配。 当您说[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是 class Ord类型的实例”。 Int可以在这里工作,因为它有一个Ord的实例,它看起来像这样:

instance Ord Int where
    (<=) = primitiveIntLessThanOrEqual

如果您离开了Ord a并且只是说select:: a -> [a] -> [a] ,那么x < y将不起作用,因为它需要 arguments 类型在Ord

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM