GHC's ViewPatterns
extension has a lot of unexpected uses. One that I've found recently is input validation.
{-# LANGUAGE ViewPatterns #-}
import Control.Monad
import Text.Printf
months :: [String]
months = words "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
Using this function:
range :: (Ord a) => a -> a -> a -> a
range lb ub x
| (x < lb) || (x > ub) = error "argument out of range"
| otherwise = x
we can put bounds on arguments:
month :: Int -> String
month (range 1 12 -> m) = months !! (m-1)
like so:
GHCi> month 3
"Mar"
GHCi> month 15
"*** Exception: argument out of range
This version provides better error messages:
-- V for 'verbose'
rangeV :: (Ord a, Show a) => String -> a -> a -> a -> a
rangeV fun lb ub x
| (x < lb) || (x > ub) = error (printf msg fun (show x) (show lb) (show ub))
| otherwise = x
where msg = "%s: argument %s is outside of range [%s,%s]"
like so:
monthV :: Int -> String
monthV (rangeV "monthV" 1 12 -> m) = months !! (m-1)
GHCi> monthV 3
"Mar"
GHCi> monthV 15
"*** Exception: monthV: argument 15 is outside of range [1,12]
Or handle failure monadically:
-- Mp for MonadPlus
rangeMp :: (MonadPlus m, Ord a) => a -> a -> a -> m a
rangeMp lb ub x = guard ((x >= lb) && (x <= ub)) >> return x
like so:
monthMaybe :: Int -> Maybe String
monthMaybe (rangeMp 1 12 -> Just m) = Just (months !! (m-1))
monthMaybe _ = Nothing
GHCi> monthMaybe 3
Just "Mar"
GHCi> monthMaybe 15
Nothing
Yeah, that's nice. Personally I prefer the latter and would prefer it with Either so that you get actual information about why it failed.
ReplyDelete> {-# LANGUAGE ViewPatterns #-}
Supposing we use the Control.Applicative.Error class.
> import Control.Applicative.Error
And we define a function that ensures X is true:
> ensure :: String -> (a -> Bool) -> a -> Failing a
> ensure err p a
> | p a = Success a
> | otherwise = Failure [err]
We can then define inRange in terms of it for Failing:
> inRange :: (Show a,Ord a) => a -> a -> a -> Failing a
> inRange lb ub x = ensure err (\a -> a>=lb && a<=ub) x where
> err = "Must be in range >=" ++ show lb ++ " and <= " ++ show ub
And our `month' and `day' functions are defined like this:
> months :: [String]
> months = words "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
> month :: Int -> Failing String
> month (inRange 1 12 -> Success m) = Success $ months !! (m-1)
> month _ = Failure ["Month must be in range 1-12."]
> days :: [String]
> days = words "Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
> day :: Int -> Failing String
> day (inRange 1 7 -> Success d) = Success $ days !! (d-1)
> day _ = Failure ["Day must be in range 1-7."]
The nice thing is we get this for free:
λ> (,) <$> month 1 <*> day 3
Success ("Jan","Wednesday")
λ> (,) <$> month 1 <*> day 12
Failure ["Day must be in range 1-7."]
λ> (,) <$> month 24 <*> day 12
Failure ["Month must be in range 1-12.","Day must be in range 1-7."]
It kind of sucks to be building strings all the time, it'd be
nicer to have proper types to represent these invariants, e.g.
> data Prop a = OutOfRange a | Empty a | WrongSize a | InvalidFormat a | Ok a
Or something like that. I suppose throwing exceptions is faster
than creating intermediate data structures.
Nice idea! But I would like to see listed in your post the alternative without view patterns:
ReplyDeletemonth :: Int -> String
month i | inRange 1 12 i = months !! (i-1)
| otherwise = error "..."
inRange :: Ord a => a -> a -> a -> Bool
inRange lb ub x = x >= lb && x <= ub
(the blog will probably clobber indentation)
Thanks for the suggestions Chris, and for mentioning Control.Applicative.Error. It definitely includes a few things I reimplemented in a recent project; I'll want to switch over.
ReplyDeleteThis is one of the things I love about (GHC) Haskell: you can often simply create a clever new "pseudo-syntax" out of the blue!!
ReplyDeleteThis "range checking pattern" would be rigid syntax in most other languages. Here it's just something that emerges from the programming paradigm.
شركة عزل اسطح بالرياض تقدم افضل خدمات عزل الاسطح في كافة انحاء الرياض وذلك لحماية كافة المباني والمنشآت من التآكل سواء من خلال ارتفاع درجات الحرارة او تسريب المياه ، كما تقدم شركتنا افضل خدمات عزل الاسطح بأعلى جودة ممكنة ، وذلك لأن شركة عزل اسطح بالرياض تعتمد علي فريق من اكفأ العمال الماهرين وذوي خبرة سنوات طويلة في مجال عزل الاسطح .
ReplyDeleteالعزل الحراري مع شركة عزل اسطح بالرياض :-
ولأن عملية العزل من احد العمليات الضرورية ولاسيما في عصرنا هذا نظراً لارتفاع درجات الحرارة كل عام عن سابقه بدرجات كبيرة ، فإنه ولا بد من عزل الاسطح ، ومن اهم اشكال العزل هو العزل الحراري ، وهو ما يفيد في الحفاظ علي درجة الحرارة الداخلية للمبني او المنشأة ثابتة بقدر المستطاع ، الامر الذي يحد من استخدام المكيفات بكثرة في فصل الصيف ، او المدافئ الكهربائية في فصل الشتاء ، وبالتالي يتم ترشيد الاستهلاك في فاتورة الكهرباء الي درجة مرضية ،كما يتم حماية افراد الاسرة من التعرض الي الامراض الناجمة من استخدام المكيفات الكهربائية .
لذلك تقدم شركة عزل الاسطح بالرياض بتقديم خدمات العزل الحراري مستخدمة في ذلك افضل ما توصلت اليه التكنولوجية من معدات حديثة ومتطورة ، الامر الذي جعل شركة عزل اسطح بالرياض مصدر ثقة جميع العملاء القدامى والجدد .
العزل المائي مع شركة عزل اسطح بالرياض :-
كما يسر شركة عزل اسطح بالرياض ان تقدم خدمات العزل المائي للأسطح ، وذلك لحمايتها من تآكل مياه الامطار لها ، وايضا حمايتها من تسريب المياه ، الامر الذي قد يهدد بسلامة العقار ومن بداخله ، فيتم حماية الاسقف من خلال شركة عزل اسطح في بالرياض بواسطة العزل المائي ، من التآكل والتلف من قبل عوامل البيئة الخارجية كالرطوبة ومياه الامطار ، فتقدم شركة عزل اسطح بالرياض من خلال فريق متميز من الخبراء والفنيين اسقف ذات حماية عالية من الهشاشة والتآكل، وذلك بأفضل الاسعار بالرياض.
تواصل معنا
0500358741
او زورو موقعنا
http://elwosta.com/
ReplyDeleteشركة مكافحة حشرات بالدمام 0590352700 ديكوريند
شركة مكافحة حشرات بالدمام
مكافحة الحشرات من الأشياء الواجب فعلها علي اتم وجه حتي نتجنب الامراض و الأوبه التي تسببها الحشرات .
و لحل مثل هذه المشكله لابد من اللجوء الي الشركات ذوي الخبره ، علي أن تكون متميزه في مكافحة الحشرات و طرق القضاء عليها .
و مما لا شك فيه أن أفضل شركة بالدمام هي شركة ديكوريند لمكافحة الحشرات .
لما تقدمه الشركه من خدمات و طرق فعاله للقضاء علي الحشرات بجميع أنواعها .
الشركه تعتمد علي العماله المدربه جيدا ، و المبيدات و الأجهزه الفعاله في القضاء علي مثل هذه الآفات الضاره.
شركة مكافحة حشرات بالدمام
شركة مكافحة حشرات بالدمام
أنواع الحشرات :
نتيجة لارتفاع درجة الحراره و نسبه الرطوبة في الدول العربيه ، تنتشر و تكثر الحشرات في كثير من المناطق و خاصة التي تطل علي المسطحات المائيه .
تؤدي تلك الآفات الضاره الي اصابه قاطني المنزل بالأمراض و شعورهم بعدم الراحه ، و تقوم أيضا بإتلاف المنتجات الغذائيه و الاثاث و الملابس .
و تتنوع انواع الحشرات كالآتي :
ذباب
بعوض
براغيث
نمل
صراصير
و غيرها الكثير
و لتنجب مثل هذه المشاكل و الأمراض و الأوبئه و المخاطر التي قد تصيب أطفالنا الصغار ، يجب القضاء علي مثل هذه الحشرات تماما و ذلك بالاستعانه بذوي الخبره .
شركة ديكوريند تتمتع بالخبره الكافيه للقضاء علي الحشرات بجميع أنواعها و أشكالها بإستخدام المعدات الجيده و العماله المدربه و المبيدات المتميزه .
لماذا شركة ديكوريند ؟
مما لاشك فيه أن أسعار شركة ديكوريند لا تقبل المنافسه اطلاقا ، لما تقدمه الشركه من خدمات جيده جدا في مقابل الأسعار التي تكون في متناول الجميع .
و تسعي الشركه دائما إلي تقديم أرقي و أفضل الخدمات ، التي ترضي جميع عملائنا الكرام ، فلا تتردد في الاتصال بنا .
اتصل الان : 0556043168 – 0590352700 شركة ديكوريند لمكافحة الحشرات بالدمام و جميع مناطق المملكة العربيه السعودية
من خدماتنا :
تنظيف فلل بالرياض
تنظيف موكيت بالرياض
تنظيف منازل بالرياض
تنظيف شقق بالرياض
تنظيف خزانات بالرياض
تنظيف مجالس بالرياض
شركة مكافحة حشرات بالدمام
ReplyDeleteشركة كشف تسربات المياه بالدمام
شركة نقل عفش بالدمام
شركة تخزين اثاث بخميس مشيط
شركة تخزين اثاث بخميس مشيط
شركة تنظيف موكيت بالرياض
ReplyDeleteشركة تنظيف مجالس بالرياض
شركة تنظيف مسابح بالرياض
شركة تنظيف كنب بالرياض
شركة مكافحة صراصير بالرياض
شركة مكافحة صراصير بالرياض
شركة مكافحة بق الفراش بالرياض
شركة مكافحة حمام بالرياض
شركة مكافحة النمل الابيض بالرياض
شركة رش مبيدات بالرياض
ReplyDeleteصور سكس متحركه عنيفه
سكس محارم اخ ينيك امة واختة
افلام سكس
فيلم الاثاره والتشويق و اغراء- رغبة فتاة – للكبار فقط 2017 مترجم +18