2016-09-04 18 views
0

は、Haskellのウィキ帳のMonadPlusの章を読んでいた:https://en.wikibooks.org/wiki/Haskell/MonadPlusハスケルwikibook MonadPlusの潜在的なエラー

digit :: Int -> String -> Maybe Int 
digit i s | i > 9 || i < 0 = Nothing 
      | otherwise  = do 
    let (c:_) = s 
    if [c] == show i then Just i else Nothing 

「doブロックは、任意の失敗パターンマッチは何も返さないことになることを保証します。」

しかし、私はdigit 1 ""を試してみましたが、 "Nothing"の代わりに間違いのある実行時エラーを生成します。

(c:_) <- return sを使用して回避できます。もしも誰かがhaskellで経験があれば、これを確認/明確にすることができれば素晴らしいだろう。

+1

は最後に、ここでは上記のコードのよりコンパクトなバージョンです。 – ErikR

答えて

2

wikibooksのコードでは、入力文字列が空の場合を考慮していません。行let (c:_) = sが実行され、sが空の場合、パターンマッチングに失敗し、例外がスローされます。あなたの提案(c:_) <- return sは、1つの違いを除いて、実際に使用されているものと非常に似ています。モナドバインド(すなわち、<-)のパターンマッチングが失敗した場合、モナドのfailメソッドが呼び出されます。今、Maybeモナドでは、failは常にNothingを返すようにdefinedであるため、doブロック全体がNothingを返すようになります。私はあなたの提案を使用することについて好きではない一つのことは、私が個人的に最もエレガントなソリューションであることがfailの使用を検討していないということであると私は場合にcase表現を使用することを好むだろう。実際には

digit :: Int -> String -> Maybe Int 
digit i s | i > 9 || i < 0 = Nothing 
      | otherwise  = 
    case s of 
     c:_ | [c] == show i -> Just i 
     _ -> Nothing 

、ご覧のとおり、doブロックを使用する必要はありません。私はパーサのとMonadPlusののちょうど悪い例だと思います

digit :: Int -> String -> Maybe Int 
digit i s | 0 <= i, i <= 9, c:_ <- s, [c] == show i = Just i 
      | otherwise = Nothing 
+0

説明をありがとう。 IOW、ウィキブックスの主張は、「ドブロックは、どんな失敗したパターンマッチでも、何も返さないことを保証する」正しいですか? –

+0

@AlbertNetymkはい、あなたはそれを言うことができます – redneb