can Haskell compiler give warning on functions that used "undefined"

Viewed 522

If I define a function using "undefined" like this, it type-checks.

add2 :: Int -> Int -> Int
add2 = undefined

Is it possible to detect if any function is using "undefined" in the function definition, and turn it into a warning?

It would be useful that in development-phase, I can use "undefined" to check if the type signature is correct before I implement the function. And then on production I can have some way to catch the mistakes that I forgot to give implementation for functions that had "undefined".

3 Answers

A good solution is to use typed holes instead of undefined along with the -fdefer-typed-holes compiler flag to make them warnings instead of errors (which is generally more useful, anyway). With this flag enabled, you would write your example like this, instead:

add2 :: Int -> Int -> Int
add2 = _

…which produces the following warning:

warning: [-Wtyped-holes]
    • Found hole: _ :: Int -> Int -> Int
    • In the expression: _
      In an equation for ‘add2’: add2 = _
    • Relevant bindings include
        add2 :: Int -> Int -> Int

Modern GHCs will even include a list of possible substitutions for the hole in the warning:

      Valid substitutions include
        add2 :: Int -> Int -> Int
        (+) :: forall a. Num a => a -> a -> a
          (imported from ‘Prelude’ (and originally defined in ‘GHC.Num’))
        (*) :: forall a. Num a => a -> a -> a
          (imported from ‘Prelude’ (and originally defined in ‘GHC.Num’))
        (^) :: forall a b. (Num a, Integral b) => a -> b -> a
          (imported from ‘Prelude’ (and originally defined in ‘GHC.Real’))
        (-) :: forall a. Num a => a -> a -> a
          (imported from ‘Prelude’ (and originally defined in ‘GHC.Num’))
        seq :: forall a b. a -> b -> b
          (imported from ‘Prelude’ (and originally defined in ‘GHC.Prim’))
        (Some substitutions suppressed; use -fmax-valid-substitutions=N or -fno-max-valid-substitutions)

If You are using hlint, You can add this rule to your .hlint.yaml:

- warning: {lhs: "undefined", rhs: undefined}

for warnings like:

Use alternative. Replace with: undefined

or You can add your own description with name attribute, for example:

- warning: {lhs: "undefined", rhs: undefined, name: Realisation is required}

Realisation is required. Replace with: undefined

You can use automatic refactoring safely, because of it just replace undefined to undefined and does not broke anything.

Also You can ignore this rule (with name attribute) for specific function:

{-# ANN functionName "HLint: ignore Realisation is required" #-}
functionName :: Int -> Int
functionName x = undefined

or for module: {-# ANN module "HLint: ignore Realisation is required" #-}

Related