2013-12-07 114 views
1

我有了兩個函數的Haskell代碼檢查函數的返回類型哈斯克爾從另一個功能

functionB :: Int -> Maybe Int 

我想要做的就是在[Int]的每個元素上遞歸併將其饋送到函數B.如果函數B返回一個Int,然後移動到下一個元素,如果它返回Nothing,那麼functionA也不會返回任何內容。

任何想法如何最好地做到這一點?

謝謝:)

+0

你的意思是你想要寫'functionA'使用'functionB'?如果多於一個「Int」給出了「Int」而不是「Nothing」,會發生什麼?只需返回工作的第一個,或返回所有工作的列表? –

回答

3

您可以使用sequence採取[Maybe Int]Maybe [Int]

functionA ints = sequence (map functionB ints) 

一般的sequencemap這個組合被稱爲mapM

functionA ints = mapM functionB ints 
+0

有點困惑於此,請您詳細說明一下? – MrD

1

你的問題有幾件事情是不明確的,因此我做了很少的假設。 functionA就像一個摺疊,因爲它轉化[Int]Maybe Int但它調用functionB到每個整數變換成Maybe Int其中Nothing結果表明在轉化的故障和其導致functionA的故障並使其返回Nothing之前摺疊所述整數。

import Control.Applicative 

functionA :: [Int] -> Maybe Int 
functionA nums = foldl (\x y -> (+) <$> x <*> y) (Just 0) $ map functionB nums 

functionB :: Int -> Maybe Int 
functionB 2 = Nothing 
functionB x = Just (x+x) 

在上面的例子中,+在摺疊操作中使用,並functionB未能在2號

0

J.亞伯拉罕回答正確的,但他不尋常的命名結果函數,它讓你感到困惑。

讓我們有整數:

ints :: [a] 

functionA :: [a] -> Maybe a 

functionB :: a -> Maybe a 

所以我們希望得到地圖functionB

functionC :: a -> Maybe [a] 
functionC ints = mapM functionB ints 

functionC有結果類型Maybe [a],不[a],所以我們使用fmap

result :: [a] -> Maybe a 
result ints = join $ fmap functionA $ functionC ints 

和w E也使用joinMaybe (Maybe a)結果

擺脫還是讓我們在同一行寫:

result :: [a] -> Maybe a 
result = join . fmap functionA . mapM functionB 

修訂

但這種解決方案總是計算所有ints。 如果我們希望停止計算,我們需要有mapIfAllJust功能,如:

result :: [a] -> Maybe a 
result = join . fmap functionA . sequence . mapIfAllJust functionB 

mapIfAllJust :: (a -> Maybe b) -> [a] -> [Maybe b] 
mapIfAllJust _ []  = [] 
mapIfAllJust f (x:xs) = go f (f x) [] xs 
where 
    go _ Nothing _ _   = [Nothing] 
    go _ pr  used []  = pr : used 
    go f pr  used (nxt:rst) = go f (f nxt) (pr : used) rst