0

Since I'm pretty sure that using global variables in Haskell is frowned upon. I'm wondering is there anyway I can achieve the following?

-- 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]

Is there anyway that I can ensure that only one of them returns true?

For example, [1,2,3,5], I would want only want listHasOdd to return True which is [True, False, False]. (Evaluated from top to bottom).

Another example, [2,4,6,8,10,12,14], the returns should be [False, True, False].

In other words, checkList [1,2,3,5] returns [True, False, False], checkList[2,4,6,8,10,12,14] returns [False, True, False]

**The last function would always be False in my example, since it is unreachable.

I know I can do an if statement to check if the previous one is True but that seems like a pretty dumb idea. Or is that actually the way to do it? (Considering Haskell "remembers" the results of the previous function)

4

2 回答 2

3

我看不出它的意义,但是

foldr foo [] $ map ($ xs) [listHasOdd, listHasEven, longList]
  where
    foo True zs = True : map (const False) zs
    foo False zs = False : zs

将产生所需的结果,并且它只会评估函数,直到其中一个返回True(或到达函数列表的末尾)。

于 2013-03-26T19:00:37.780 回答
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]但即使这样也很愚蠢:为什么不直接使用 ,而不是生成 a 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`)
于 2013-03-26T19:18:11.247 回答