2016-11-14 15 views
2

列表理解我想寫的東西是這樣的:如何可以有條件我的模式匹配的哈斯克爾

> [(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)] 

把條件列表,並使用<-提取結果似乎特設

我想:

> [(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)] 

有沒有做到這一點的優選方式。

我知道這個問題可以用其他方式解決,但我們假設我想在條件列表理解中模式匹配。 有沒有一個很好的方法來做到這一點?

謝謝。

+1

從[我可以問什麼主題?](http://stackoverflow.com/help/on-topic):「...一個實用的*,可回答的問題,這是軟件開發所特有的」 。你有什麼實際的理由需要在列表理解中進行這種類型的模式匹配? – chepner

+0

這裏你不需要模式匹配。 '[(我,div我2)|我< - [2,4..10]]'就足夠了。 – lovasoa

+0

「將條件放在列表中,並使用'<-'來提取結果似乎是臨時的」,如果不是'Just j < - [somethingThatReturnsMaybe i]'您寫了'Just j < - return $ somethingThatReturnsMaybe i'? – Cactus

回答

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

模式在哪匹配? – Thilo

+2

@Thilo沒有,因爲沒有必要,我想知道OP最終需要什麼,因爲這看起來是一個XY問題。 – chi

+3

也許是這樣,但他說「這個問題可以通過其他方式解決,但讓我們假設我想在列表理解中有條件地進行模式匹配「 – Thilo