Commits

Aleksey Khudyakov committed 807b3b0

Add special return type for equation solvers.

Ported from statistics

Comments (0)

Files changed (1)

Numeric/Tools/Equation.hs

+{-# LANGUAGE DeriveDataTypeable #-}
 -- |
 -- Module    : Numeric.Tools.Equation
 -- Copyright : (c) 2011 Aleksey Khudyakov
 --
 -- Numerical solution of ordinary equations.
 module Numeric.Tools.Equation ( 
-    solveBisection
+    -- * Data type
+    Root(..)
+  , fromRoot
+    -- * Equations solversv
+  , solveBisection
   ) where
 
-import Numeric.IEEE (epsilon)
+import Numeric.IEEE        (epsilon)
 
+import Control.Applicative
+import Control.Monad       (MonadPlus(..), ap)
+import Data.Typeable       (Typeable)
+
+
+
+-- | The result of searching for a root of a mathematical function.
+data Root a = NotBracketed
+            -- ^ The function does not have opposite signs when
+            -- evaluated at the lower and upper bounds of the search.
+            | SearchFailed
+            -- ^ The search failed to converge to within the given
+            -- error tolerance after the given number of iterations.
+            | Root a
+            -- ^ A root was successfully found.
+              deriving (Eq, Read, Show, Typeable)
+
+instance Functor Root where
+  fmap _ NotBracketed = NotBracketed
+  fmap _ SearchFailed = SearchFailed
+  fmap f (Root a)     = Root (f a)
+
+instance Monad Root where
+  NotBracketed >>= _ = NotBracketed
+  SearchFailed >>= _ = SearchFailed
+  Root a       >>= m = m a
+  return = Root
+
+instance MonadPlus Root where
+  mzero = SearchFailed
+  r@(Root _) `mplus` _ = r
+  _          `mplus` p = p
+
+instance Applicative Root where
+  pure  = Root
+  (<*>) = ap
+
+instance Alternative Root where
+  empty = SearchFailed
+  r@(Root _) <|> _ = r
+  _          <|> p = p
+
+-- | Returns either the result of a search for a root, or the default
+-- value if the search failed.
+fromRoot :: a                   -- ^ Default value.
+         -> Root a              -- ^ Result of search for a root.
+         -> a
+fromRoot _ (Root a) = a
+fromRoot a _        = a
 
 
 -- | Solve equation @f(x) = 0@ using bisection method. Function is
 solveBisection :: Double             -- ^ Required absolute precision
                -> (Double,Double)    -- ^ Range
                -> (Double -> Double) -- ^ Equation
-               -> Maybe Double
+               -> Root Double
 solveBisection eps (a,b) f
-  | a >= b      = Nothing
-  | fa * fb > 0 = Nothing
-  | otherwise   = Just $ bisectionWorker (abs eps) f a b fa fb
+  | fa * fb > 0 = NotBracketed
+  | otherwise   = Root $ bisectionWorker (abs eps) f a b fa fb
   where
     fa = f a
     fb = f b
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.