因为我很确定在Haskell中使用全局变量是不受欢迎的。我想知道无论如何我可以实现以下目标吗?
-- list has elements that are odd
listHasOdd :: [Integer] -> Bool
-- list has elements that are even
listHasEven :: [Integer] -> Bool
--list has a length > 5
longList :: [Integer] -> Bool
-- Maps the function to a [Bool]
-- This function cannot be modified to fix the problem.
checkList :: [Integer] -> [Bool]
checkList xs = map (\ y -> y xs) listChecker
where listChecker = [listHasOdd, listHasEven, longList]
无论如何,我可以确保只有其中一个返回真实吗?
例如,[1,2,3,5],我只想要listHasOdd返回 真,这是[真,假,假]。 (从上到下评估)。
另一个例子,[2,4,6,8,10,12,14],返回值应为[False,True,False]。
换句话说,checkList [1,2,3,5]返回[True,False,False],checkList [2,4,6,8,10,12,14]返回[False,True,False]
**在我的例子中,最后一个函数总是为False,因为它无法访问。
我知道我可以做一个if语句来检查前一个是True
但是这看起来很愚蠢。或者这实际上是这样做的方式? (考虑到Haskell“记得”前一个函数的结果)
答案 0 :(得分:3)
我没有看到它的意义,但
foldr foo [] $ map ($ xs) [listHasOdd, listHasEven, longList]
where
foo True zs = True : map (const False) zs
foo False zs = False : zs
会产生所需的结果,它只会评估函数,直到其中一个函数返回True
(或者到达函数列表的末尾)。
答案 1 :(得分:2)
这是我能想到的最好的。例如,它通过相对无痛的方式来处理扑克手的可能结果的数量。
data Outcome
= ListHasOdd
| ListHasEven
| LongList
| Nope
deriving Eq
outcomeFromList :: [Integer] -> Outcome
outcomeFromList xs
| any odd xs = ListHasOdd
| any even xs = ListHasEven
| 5 < length xs = LongList
| otherwise = Nope
listHasOdd = (ListHasOdd ==) . outcomeFromList
listHasEven = (ListHasEven ==) . outcomeFromList
longList = (LongList ==) . outcomeFromList
但即使这是愚蠢的:为什么不直接使用[Bool]
而不是生成Outcome
?
编辑或者我们可以关注的含义。
listHasOdd xs = any odd xs
listHasEven [] = False
listHasEven xs = all even xs
-- if not all of them are even, then at least one must be odd,
-- and `listHasOdd` would give `True`
longList _ = False
-- if the list has at least 5 elements,
-- then either the list has at least one odd element
-- (and `listHasOdd` would give `True`)
-- or the list has at least five even elements
-- (and `listHasEven` would give `True`)