2012-05-16 31 views
14

Kullanıcılar ve gruplar arasında bir grup kullanıcı, grup ve eşleme var. Bu kümeleri işlemek için çeşitli işlevlerim var, ancak var olmayan bir kullanıcı için bir kullanıcı < -> grup eşlemesi ekleyememeli ya da hala kullanıcı olarak üye olan bir grubu kaldıramamalı. Vs.Haskell "istisnalar"

temel olarak, bu işlevlerin, arayan tarafından açıkça ele alınması gereken "istisnalar" atmasını istiyorum.

Ben ilk böyle bir şey dönen düşündüm:

data Return r e = Success r | Exception e 

Ve arayan Exception karşı desen maç, onlar umarım derleyici uyarı alırsınız başarısız veya eğer en azından bariz bir çalışma zamanını var bir sorun olduğunda hata.

Bu en iyi yaklaşım mıdır ve bunu yapan önceden paketlenmiş bir çözüm var mı? Not Ben IO Monad değil, saf kod, "istisnalar" atmak ve yakalamak gerekir.

cevap

19

Evet, bu iyi bir yaklaşım ve standart kitaplıktadır: Return r e, Either e r ile aynıdır. IO'daki istisnaları da kullanacağınız gibi kod yazabilirsiniz (ör. Her adımda desen eşleştirmesiyle hataları açıkça işlemek zorunda kalmadan): Either için Monad örneği hataları iletir, tıpkı Maybe Monad'ın yaptığı gibi Bir hata durumunda ek e değeri). Örneğin:

data MyError 
    = Oops String 
    | VeryBadError Int Int 

mightFail :: T -> Either MyError Int 
mightFail a = ... 

foo :: T -> T -> Int -> Either MyError Int 
foo a b c = do 
    x <- mightFail a 
    y <- mightFail b 
    if x == y 
     then throwError (VeryBadError x y) 
     else return (x + y + c) 

Eğer mightFail a veya mightFail b döner sonra Left someError de foo a b c irade; hatalar otomatik olarak yayılır. (Burada, throwError, Left yazma Control.Monad.Error işlevleri kullanmanın sadece güzel bir yoludur; bu istisnaları yakalamak için de catchError var.) Sizin tarif edilmektedir

11

Return r e tipi tam olarak standart tip

data Either a b = Left a | Right b 
olduğunu

mtl paketinin "error monad" (daha uygun bir ismi "istisnai monad") kullanmak isteyebilirsiniz. (Alternatif olarak, mtl kullanmak istemiyorsanız, monadLib paketinde ExceptionT var.) Bu, throwError ve catchError numaralarını çağırarak, salt kodda hata işleme gerçekleştirmenizi sağlar. Here Nasıl kullanacağınızı gösteren bir örnek bulabilirsiniz.