3

シナリオ: AST からボトムアップで値を構築するインタープリターがあります。特定のノードにはパーミッション (追加のブール式) が付属しています。権限の失敗は伝播するはずですが、AST の上位のノードに権限がある場合、成功すると計算が回復され、エラーの伝播が停止します。

Error MyError MyValue最初はモナドで十分だMyErrorPermError思っていました. ただし、ハンドラーに到達するまでにはなくなっています。最終的には PermError にフィールドを渡させてハンドラーがフィールドを復元できるようにする方法があると思いますが、おそらくそれは見苦しく、各ステップで例外をチェックすると、例外発生の概念が無効になります。catchErrorPermErrorMyValueMyValue

私は別の抽象化を考えようとしています。Either AllErrorsExceptPermError (Maybe PermError, MyValue)基本的に、私はデータ型またはもっと単純に返す必要があります(Maybe AllErrors, MyValue)(他のエラーは回復不能で、エラー モナドにかなりよく適合します)。操作がどのように連鎖されているか。私の Haskell の知識はこれまでしかありません。この状況で haskell をどのように活用しますか?

私がこれを書いている間に、私はアイデアを思いつきました (SO は派手なラバーダックです): 型 (a, b) を内部的に処理するモナド (そして、モナドの計算が終了したときに最終的にそれを返します。runMyMonad)、ただし、型 b をできるだけ直接操作できるようにします。何かのようなもの

data T = Pass | Fail | Nothing
instance Monad (T , b) where
  return v = (Nothing, v)
  (Pass, v) >>= g = let (r', v') = g v in (if r' == Fail then Fail else Pass, v')
  (Fail, v) >>= g = let (r', v') = g v in (if r' == Pass then Pass else Fail, v')
  (Nothing, _) >>= g = error "This should not have been propagated, all chains should start with Pass or Fail"

エラーは T に単純化されており、instance行にはおそらく構文エラーがありますが、その考えは理解できるはずです。これは理にかなっていますか?

4

1 に答える 1

2

Stateアクセス許可と値の計算にモナドを使用し、それをErrorTモナドトランスフォーマー内にラップしてエラーを処理できると思います。以下はアイデアを示す例です。ここでは、計算はリストを合計しています。許可はリスト内の偶数の数であり、エラー状態はリストに 0 がある場合です。

import Control.Monad.Error
import Control.Monad.State

data ZeroError = ZeroError String
              deriving (Show)

instance Error ZeroError where


fun :: [Int] -> ErrorT ZeroError (State Int) Int
fun [] = return 0
fun (0:xs) = throwError $ ZeroError "Zero found"
fun (x:xs) = do
  i <- get
  put $ (if even(x) then i+1 else i)
  z <- fun xs
  return $ x+z


main = f $ runState (runErrorT $ fun [1,2,4,5,10]) 0
       where
         f (Left e,evens) = putStr $ show e
         f (Right r,evens) = putStr $ show (r,evens)
于 2013-07-16T10:33:09.297 に答える