2015-11-10 22 views
0

我在Haskell哈斯克爾:函數薪酬返回Maybe類型:異常與fromJust功能

payment :: [(Integer , Integer)] -> Integer -> [(Integer , Integer)] -> Maybe [(Integer , Integer)] 
payment portemonnaie amount cashier | content (fromJust (pay portemonnaie amount)) - amount == 0 = Just [] 
            | pay portemonnaie amount == Nothing = Nothing 
            | otherwise = payExact cashier (content (fromJust (pay portemonnaie amount)) - amount) 

這裏的問題是寫了下面的功能。通過詢問

*** Exception: Maybe.fromJust: Nothing 

我試圖阻止:所以當功能「買單」返回Nothing我得到下面的異常

| pay portemonnaie amount == Nothing = Nothing 

但顯然這是不可能的。有人有更聰明的方式來構建這個?謝謝

+6

使用模式匹配,避免部分功能。 – chi

+2

也'map','fromMaybe'或'也許'可能是你想要在這裏;) – Carsten

回答

3

問題是,Nothing檢查電話fromJust。在你解決它的方式,它應該是這樣的:

payment :: [(Integer , Integer)] -> Integer -> [(Integer , Integer)] -> Maybe [(Integer , Integer)] 
payment portemonnaie amount cashier | pay portemonnaie amount == Nothing = Nothing 
            | content (fromJust (pay portemonnaie amount)) - amount == 0 = Just [] 
            | otherwise = payExact cashier (content (fromJust (pay portemonnaie amount)) - amount) 

然而,它可能仍然會更好。首先,自2010年以來哈斯克爾(或在Haskell 98與PatternGuards擴展名),它更容易寫:

payment :: [(Integer , Integer)] -> Integer -> [(Integer , Integer)] -> Maybe [(Integer , Integer)] 
payment portemonnaie amount cashier | Nothing <- pay portemonnaie amount = Nothing 
            | Just paid <- pay portemonnaie amount, content paid - amount == 0 = Just [] 
            | otherwise = payExact cashier (content paid - amount) 

此外,您可以通過使用where條款縮短一些事情:

payment :: [(Integer , Integer)] -> Integer -> [(Integer , Integer)] -> Maybe [(Integer , Integer)] 
payment portemonnaie amount cashier | Nothing <- mayHavePaid = Nothing 
            | Just paid <- mayHavePaid, content paid - amount == 0 = Just [] 
            | otherwise = payExact cashier (content paid - amount) 
    where 
    mayHavePaid = pay portemonnaie amount 
+0

謝謝你,這是非常有幫助的。是的,我只是在看守那些守衛和某種程度的監督,來自Just-call的人也是第一個後衛。也感謝您的進一步提示! – Noli

0

如果沒有任何擴展,仍然可以用相當可讀的方式來編寫(實際上,我認爲,比使用模式守護的答案更易讀)。首先,注意到一件事,你在所有的情況下做的是pay portemonnaie amount,那你必須做取決於函數的結果不同的東西:所以,把它放在第一,和模式匹配就可以了:

case pay portemonnaie amount of 
    -- ... 

在沒有的情況下是很容易,所以你可以平凡添加進來,並留下一個空白的只是:現在

case pay portemonnaie amount of 
    Nothing -> Nothing 
    (Just receipt) -> -- ... 

,如果有一個剛(這我在這裏呼籲收據,因爲我不是確定它在你的域中是什麼),那麼你總是需要計算剩餘的數量,所以讓我們把它放在where子句中:

case pay portemonnaie amount of 
    Nothing -> Nothing 
    (Just receipt) -> -- ... 
    where outstanding = content receipt - amount 

現在,所有剩下的就是填補了不同的保護條款對於剛剛模式,這是現在很容易,相關數值已經綁定:

case pay portemonnaie amount of 
    Nothing -> Nothing 
    (Just receipt) | outstanding == 0 -> Just [] 
       | otherwise -> payExact cashier outstanding 
    where outstanding = content receipt - amount 

當然插槽,表達回實際功能的主體:

payment :: [(Integer, Integer)] -> Integer -> [(Integer, Integer)] -> Maybe [(Integer, Integer)] 
payment portemonnaie amount cashier = 
    case pay portemonnaie amount of 
    Nothing -> Nothing 
    (Just receipt) | outstanding == 0 -> Just [] 
        | otherwise -> payExact cashier outstanding 
     where outstanding = content receipt - amount