2013-03-01 94 views
3

我有以下功能簡化代碼[]

type Assignment = [(Ref, Val)] 

predi2 :: [(Val,Val)] -> Ref -> Ref -> (Maybe Assignment -> [Maybe Assignment]) 
predi2 f k1 k2 = \ma -> case ma of 
    Nothing -> [Nothing] 
    Just a -> case lookup k1 a of 
     Nothing -> [Nothing] 
     Just e1 -> case lookup k2 a of 
      Nothing -> [Nothing] 
      Just e2 -> if elem (e1, e2) f 
       then [Just a] 
       else [] 

鑑於或許所有的情況下,我想我可以把它簡化爲東西也許單子裏面更簡單:

predi2 :: [(Val,Val)] -> Ref -> Ref -> (Maybe Assignment -> [Maybe Assignment]) 
predi2 f k1 k2 = [\ma -> do 
    a <- ma 
    e1 <- lookup k1 a 
    e2 <- lookup k2 a 
    if elem (e1, e2) f then (return a) else ???] 

但我的問題是最後的其他問題,我需要什麼都不返回。

這是我的問題:是否有可能以[f a] = []這樣的方式返回任何內容?

回答

9

不,不是。

我會寫你predi2功能更是這樣的:

predi2 f k1 k2 ma = fromMaybe [Nothing] $ do 
    a <- ma 
    e1 <- lookup k1 a 
    e2 <- lookup k2 a 
    if elem (e1, e2) f then return [Just a] else return [] 

  • 後處理的單子計算,使用fromMaybe
  • 有單子計算裏面的列表,而不是在它之外
  • if語句的False分支計數成功(按照一次計算)
+0

謝謝,這是完美的! – 2013-03-01 19:05:34

2

我認爲這是可能的,如果我理解正確的問題。

令我感到震驚的是,您試圖跟蹤兩種不同類型的故障,空列表指示最終elem查找失敗。 Maybe表示(1)原始的Maybe AssignmentNothing或者(2)lookup失敗。我們可以更清楚地瞭解這一點。返回類型應該是這樣的

data FailureType = Existence | SeenInF 
Either FailureType Assignment 

然後我們就在Maybe類型的故障使用errors模塊轉換成Either秒。

import Control.Error 
predi2 :: [(Val, Val)] -> Ref -> Ref -> Maybe Assignment -> Either FailureType Assignment 
predi2 f k1 k2 ma = do a <- note Existence ma 
         e1 <- note Existence $ lookup k1 a 
         e2 <- note Existence $ lookup k2 a 
         note SeenInF $ guard $ (e1, e2) `elem` f 
         return a 

該解決方案是一個有些奇怪,因爲它涉及到兩個失敗單子之間轉換,MaybeEither,但note是實現這一目的一個非常有用的功能。