我不明白这个功能是如何工作的

时间:2014-07-29 21:20:33

标签: haskell

estaLivre lg pls = head [s | (l,s) <- pls, l==lg] == 0

此函数接收两个列表作为参数。第一个是剧院椅子的坐标。与(1, 1)第1行第1列一样。pls是剧院中椅子的描述。 pls由椅子的坐标和1或0组成,它告诉椅子是否被拿走(1)或者不是(0)。这样的事情:pls = [((1, 1), 1), ((1, 2), 0)]主持(1, 1)。主席(1, 2)不是。

我不明白这是怎么回事。 head获取列表的第一个元素并查看它是否等于0(是吗?)但s不是第一个元素。那么这是如何工作的?

我已经做了一些测试,看看它是如何工作的,显然,head采用的是'|'之前的元素。在这种情况下,'s'。我的一个测试是担任[y | (x, y) <- xs, x == y^1/2]的负责人。它返回y的值。我对[x | (x, y) <- xs, y == x^2]做了同样的事情,并返回x。但它仍然让我感到困惑,因为我被教导说头部是列表中的第一个元素。有人可以向我解释一下吗?

2 个答案:

答案 0 :(得分:2)

让我们从参数开始:lg是您想要测试的位置,pls是位置列表,其中每个位置都是元组(坐标,如果坐标是免费的)然后0其他1)。

列表推导用于从列表pls中选择在输入中给出相同坐标的位置,即lg,然后仅选择元组的第二部分,即if这个职位是免费的:

[s | (l,s) <- pls, l==lg]

由于pls是一个列表,因此其中的多个元素可能满足l==lg,例如当pls = [((1,1),0),((1,1),0)]上面的表达式将返回[0,0]时,因此,您必须使用head来提取满足谓词的第一个匹配项:

head [s | (l,s) <- pls, l==lg]

这将通过返回0告诉您该位置是否免费,或者通过返回1来获取该位置,最终测试== 0将转换0或{ {1}}为布尔值。

作为旁注,我想说这个功能很糟糕且不安全,特别是因为它使用1来提取给定坐标的一个可能出现位置。应该重写它以使用head而不是maps并使用lists代替bool来说明是否采取了这种立场。

答案 1 :(得分:1)

head函数定义为

head :: [a] -> a
head (x:xs) = x
head [] = error "Prelude.head: empty list"

所有这一切都是从列表中抓取第一个元素。

您对此感到困惑的是列表理解语法。这是一种语法,可以让您非常干净地编写列表操作,而无需使用mapfilter或列出monadic语法(这是另一天的主题)这样的函数。简而言之,如果您看到类似

的内容
[function x | x <- someList, condition x]

这大致相当于

map function (filter condition someList)

<-视为迭代someList中的每个元素并将该值分配给x,然后根据条件函数condition进行检查,构建列表在其中,将function应用于每个元素。如果你想迭代多个列表,这个语法也很有用,但我会让你自己玩它(尝试GHCi中的[(x, y) | x <- [1..5], y <- [6..10]]之类的东西来看看会发生什么)。


所以在你的情况下,你有

estaLivre lg pls = head [s | (l,s) <- pls, l==lg] == 0

如果我们使用上面的规则,我们可以将其转换为

estaLivre lg pls = head (map snd $ filter (\(l, s) -> l == lg) pls) == 0

如果元组没有模式匹配,这可能会更明显,你可以把原来的函数写成

estaLivre lg pls = head [snd x | x <- pls, fst x == lg] == 0

因此列表[s | (l,s) <- pls, l==lg]将返回给定行/列坐标s的所有座位占用lg的列表,然后head获取第一个元素该列表,然后与0进行比较。