Looking for a standard Haskell icon before I embody it

I have defined a datatype RuleFile

and I am writing a function that explores RuleFile

with a number of predicates, accumulating warning lines as they go.

rfWarnings :: RuleFile -> [String]
rfWarnings rf = let warnings = [((\rf -> length (neigh rf) > 3), "warning: unknown extra information in the neighborhood, discarding it and moving on"),
                               <more warnings> ]
                in <process> warnings

      

Is there some kind of out-of-the-box haskell function for <process>

? Or maybe I don't think about it by the idiomatic haskell method, and is there another recommended approach? I am using Control.Monad.Except

for errors, but my current thinking is that I want to handle warnings separately and output messages to stderr.

Later I will use it with something like ...

main :: IO ()
main = do
 <some stuff>
 ruleFiles <- <produce them>
 mapM (hPutStr stderr) (map rfWarnings ruleFiles)
 <other stuff>

      

+3


source to share


3 answers


Not sure if this works for your application - but, the idiomatic thing might be to change the type of your predicates: instead of a fixed string and a function that returnsBool

(but in case Nothing

you don't really need a string), use only the function - that returns Maybe String

. Then what you are asking for becomes very simple: apply all the functions in the list to the given argument and collect the values Just

.

rfWarnings' :: RuleFile -> [String]
rfWarnings' rf = catMaybes $ map ($rf) warnings
 where warnings = [ \rf -> guard (length (neigh rf) > 3) >> return
                             "warning: unknown extra information in the neighborhood, discarding it and moving on"
                  , {-more warnings-}
                  ]

      

To avoid repeating this guard

in Maybe

MonadPlus

, you can define an operator that binds regular predicates directly to the strings you want:



 where warnings = [ (\rf -> length (neigh rf) > 3) ==>
                             "warning: unknown extra information in the neighborhood, discarding it and moving on"
                  , {-more warnings-}
                  ]
       pred ==> str = guard pred >> return str

      

It looks like it's even better:

 where warnings = [ "warning: unknown extra information in the neighborhood, discarding it and moving on"
                      \<= \rf -> length (neigh rf) > 3
                  , {-more warnings-}
                  ]
       str \<= pred = guard pred >> return str

      

+4


source


To do this, you can use Writer

:

import Control.Monad.Writer

rfWarnings rf = execWriter $ do
    unless (length (neigh rf) <= 3) $ tell "Too much neigh!"
    unless (isFrobulastic rf) $ tell "Frobulation mismatch!"

      

This has the advantage that it is very easy to put together rfWarnings

smaller pieces, for example.



rfWarnings rf = execWriter $ do
  unless (looksOK rf) $ tell "Completely b0rken!"
  mapM_ partWarning (parts rf)

      

and also, I would rather use unless

than when

because I think that describing the correct state is better than describing the wrong one.

+4


source


rfWarnings rf = let warnings = [((\rf -> length (neigh rf) > 3), "warning: ..."),
                                <more warnings> ]
                in [ message | (predicate, message) <- warnings, predicate rf ]

      

or even by removing the lambda,

rfWarnings rf = let warnings = [(length (neigh rf) > 3, "warning: ..."),
                                <more warnings> ]
                in [ message | (predicate, message) <- warnings, predicate ]

      

or even (a little more critical)

rfWarnings rf = let warnings = [(length (neigh rf) > 3, "warning: ..."),
                                <more warnings> ]
                in [ message | (True, message) <- warnings ]

      

or even (shorter but less readable)

rfWarnings rf = let warnings = [(length (neigh rf) > 3, "warning: ..."),
                                <more warnings> ]
                in map snd $ filter fst warnings

      

+3


source







All Articles