我想写这样的东西:
> [(i, j) | i <- [1..10],
Just j <- [if (even i) then Just (i `div` 2) else Nothing]]
[(2,1),(4,2),(6,3),(8,4),(10,5)]
将条件放入列表并使用<-
提取结果似乎是 ad hoc 。
我试过了:
> [(i, j) | i <- [1..10],
let Just j = if (even i) then Just (i `div` 2) else Nothing]
但那失败了。
以下作品但似乎很尴尬:
> [(i, j) | i <- [1..10],
let x = if (even i) then Just (i `div` 2) else Nothing,
isJust x,
let Just j = x]
[(2,1),(4,2),(6,3),(8,4),(10,5)]
有没有首选方法可以做到这一点。
我知道这个特殊问题可以通过其他方式解决,但我们假设我想在列表理解中有条件地模式匹配。 有没有好办法呢?
感谢。
答案 0 :(得分:2)
这对你来说是否可以接受?
[(i, j) | i <- [1..10], even i, let j = i `div` 2]
另一个(IMO更糟)选项:
[(i, j) | i <- [1..10],
j <- if even i then [i `div` 2] else []]
又一个:
do i <- [1..10]
j <- guard (even i) >> return (i `div` 2)
return (i,j)
又一个:
[(i, j) | i <- [1..10],
j <- [i `div` 2 | even i]]
真的有点过分,强烈不推荐:
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
testEvenRight :: Integral a => Either b a -> Maybe a
testEvenRight (Right n) | even n = Just n
testEvenRight _ = Nothing
pattern EvenRight n <- (testEvenRight -> Just n)
list1 = [Right 2, Right 1, Left "abc", Right 4, Right 5]
list2 = [(i,j) | EvenRight i <- list1 , let j = i `div` 2]