Difference between revisions of "Means of expression"

From HaskellWiki
Jump to navigation Jump to search
(qualified names instead of naming conventions)
Line 121: Line 121:
 
...
 
...
 
</haskell>
 
</haskell>
and thus assert one naming style in his module.
+
and thus assert a consistent naming style in his module.
   
  +
Find out about more style questions on [[Import modules properly|importing]] and [[qualified names]].
   
 
== See also ==
 
== See also ==

Revision as of 10:56, 28 January 2011

Programming languages have different types of means of expression:

  • Primary means of expression: variables, types, parentheses, etc. in general all things that are relevant to the compiler
  • Secondary means of expression: layout, comments, etc. that is language elements that are irrelevant for the compiler, and thus are made exclusively for the human reader

In Haskell (as well as in Python) one has to weaken that because layout is interpreted by the compiler.

It is generally good style to remember the rule:

Prefer primary means of expression to secondary ones!

The reason is, that elements that are relevant to the compiler are checked by the compiler and can be processed by documentation, analysis and refactoring tools. Thus it is not good style to comment intensively if the language provides primary ways to express our ideas.

Examples

Expressive variable names instead of comments

I recently saw code like

-- | first name
fn :: Person -> String

-- | surname
sn :: Person -> String

It was hard to read the program because there were several other two-character function names to remember, and the comment was only attached to the function definition, not the calls. The comments would be better replaced by expressive function names like

firstName :: Person -> String
surname :: Person -> String

Variables instead of comments

solveSLE2 :: Fractional a => ((a,a), (a,a)) -> (a,a) -> (a,a)
solveSLE2 ((a00,a10),(a01,a11)) (b0,b1) =
   let det = a00*a11 - a10*a01
   in  (-- determinant with first column replaced by b
        (b0*a11 - b1*a01) / det,
        -- determinant with second column replaced by b
        (a00*b1 - a10*b0) / det)

It is likely that logical units like the 2x2 determinant are reused later (e.g. for the vector product) or that they should be tested separately. Thus it is better to factor them out into separate functions.

solveSLE2 :: Fractional a => ((a,a), (a,a)) -> (a,a) -> (a,a)
solveSLE2 a@(a0,a1) b =
   let det = det2 a
   in  (det2 (b, a1) / det,
        det2 (a0, b) / det)

det2 :: Num a => ((a,a), (a,a)) -> a
det2 ((a00,a10),(a01,a11)) = a00*a11 - a10*a01

Types instead of comments

-- | returned list contains at most one element
foo :: [a] -> [a]

This can be expressed without comments more safely and concisely

foo :: [a] -> Maybe a

Qualification instead of identifier prefix/suffix conventions

You may define

module File where

openFile :: FilePath -> IO Handle

and intend to import that unqualified

import File

main :: IO ()
main = do
   h <- openFile "myfile"
   ...

in other modules, or you can define

module File where

open :: FilePath -> IO Handle

that would fit for qualified import as in

import qualified File

main :: IO ()
main = do
   h <- File.open "myfile"
   ...

The second way would use primary means of the language (modules and qualified imports) whereas the first way uses secondary means of the language (naming convention). The naming convention cannot be checked, that is fileOpen and openFill would be accepted by any Haskell compiler and it forces the user to follow this convention, leading to respect different conventions from different packages that are imported in one module, e.g. type name in the identifier as prefix vs. suffix. Using qualified imports, the importer can choose an abbreviation that he likes, say:

import qualified File as F

main :: IO ()
main = do
   h <- F.open "myfile"
   ...

and thus assert a consistent naming style in his module.

Find out about more style questions on importing and qualified names.

See also

Johannes Waldmann: Haskell mit Stil