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
。但它仍然让我感到困惑,因为我被教导说头部是列表中的第一个元素。有人可以向我解释一下吗?
答案 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"
所有这一切都是从列表中抓取第一个元素。
您对此感到困惑的是列表理解语法。这是一种语法,可以让您非常干净地编写列表操作,而无需使用map
,filter
或列出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
进行比较。