Let’s take a stab at writing a predicate that will check for a C++ source file that is over 128 KB in size:
-- file: ch09/BetterPredicate.hs myTest path _ (Just size) _ = takeExtension path == ".cpp" && size > 131072 myTest _ _ _ _ = False
This isn’t especially pleasing. The predicate takes four arguments, always ignores two of them, and requires two equations to define. Surely we can do better. Let’s create some code that will help us write more concise predicates.
Sometimes, this kind of library is referred to as an embedded domain-specific language: we use our programming language’s native facilities (hence embedded) to write code that lets us solve some narrow problem (hence domain-specific) particularly elegantly.
Our first step is to write a function that returns one of its arguments. This one extracts the path from the arguments passed to a Predicate:
-- file: ch09/BetterPredicate.hs pathP path _ _ _ = path
If we don’t provide a type signature, a
Haskell implementation will infer a very general type for this function.
This can later lead to error messages that are difficult to interpret,
so let’s give
pathP a type:
-- file: ch09/BetterPredicate.hs type InfoP a = FilePath -- path to directory entry -> Permissions -- permissions -> Maybe Integer -- file size (Nothing if not file) -> ClockTime -- last modified -> a pathP :: InfoP FilePath
We’ve created a type synonym that we can use as shorthand for writing other, similarly structured functions. ...