> One of the best bad example is the use of boolean as arguments.

Oh, yes.  That's a pet peeve of mine.  About 99% of boolean arguments
should be meaningful two-valued enumerated types.  It's literally a
one-liner to create such an enumerated type, so there's no excuse.


The documentation effect and type safety provided by two-valued enumerated types is indeed much greater. But one needs a conversion from Bool to the enumeration if one wants to pass the result of a logic operation to the function. What about records with named fields, especially if more options are needed?

data CreateDirectoryOptions = Cons {createParents :: Bool}

createDirectory (Cons {createParents = True}) "dir"

Hummmm.... I think I like this. Something like the following allows a simple way to make the call site concise and provide defaults at the same time. Additional plus -- adding options requires no call-site code changes.


---------------------------------------

import Control.Monad

-- provide "opts" which should be a labeled record
-- of default options
class FunctionOptions a where opts :: a

-- alias for readability when you don't want to change
-- the default options
defaults = opts

-- create a datatype for each function which needs some flags
data CreateDirectoryOptions
   = CreateDirectoryOptions
    { createParents :: Bool
    , barFlag :: Bool
    , andNow :: Bool
    , aWholeBunch :: Bool
    , ofOther :: Bool
    , seldomEverUsed :: Bool
    , esotericOptions :: Bool
    }

-- set the flag defaults
instance FunctionOptions CreateDirectoryOptions
  where opts =
          CreateDirectoryOptions
          { createParents = False
          , barFlag = True
          , andNow = True
          , aWholeBunch = True
          , ofOther = False
          , seldomEverUsed = True
          , esotericOptions = False
          }

createDirectory :: CreateDirectoryOptions -> FilePath -> IO ()
createDirectory o path =
        do when (createParents o) (putStrLn "creating parents")
           when (barFlag o) (putStrLn "bar flag true")
           putStrLn ("creating "++path)
           return ()

-- readable AND typesafe :-)
main = do createDirectory opts{ createParents = True } "foo"
          createDirectory defaults "baz"

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to