ideas-0.5.8: src/Service/ExerciseList.hs
{-# LANGUAGE ExistentialQuantification, Rank2Types #-}
-----------------------------------------------------------------------------
-- Copyright 2009, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Service.ExerciseList
( exerciseList, findExercises, getExercise
, openMathExercises, findOpenMathExercises, getOpenMathExercise
, OpenMathExercise(..)
, resolveExerciseCode
) where
import Common.Utils (Some(..))
import Common.Exercise
import Data.Char
import Domain.Math.Expr
import qualified Domain.LinearAlgebra as LA
import qualified Domain.Logic as Logic
import qualified Domain.RelationAlgebra as RA
import qualified Domain.Math.DerivativeExercise as Math
import qualified Domain.Math.Numeric.Exercises as Math
import qualified Domain.Math.Equation.CoverUpExercise as Math
import qualified Domain.Math.Polynomial.Exercises as Math
-- List with all known exercises
exerciseList :: [Some Exercise]
exerciseList =
[ -- logic and relation-algebra
Some Logic.dnfExercise
, Some Logic.dnfUnicodeExercise
, Some RA.cnfExercise
] ++
[ Some e | OMEX e <- openMathExercises ]
-----------------------------------------------------------------------------
-- All mathematical exercises are supported by the OpenMath standard, and
-- require an extra type constraint
data OpenMathExercise = forall a . IsExpr a => OMEX (Exercise a)
openMathExercises :: [OpenMathExercise]
openMathExercises =
[ -- basic math
OMEX Math.naturalExercise, OMEX Math.integerExercise
, OMEX Math.rationalExercise, OMEX Math.fractionExercise
, OMEX Math.coverUpExercise
, OMEX Math.linearExercise
, OMEX Math.quadraticExercise
, OMEX Math.higherDegreeExercise
, OMEX Math.derivativeExercise
-- linear algebra
, OMEX LA.gramSchmidtExercise
, OMEX LA.linearSystemExercise
, OMEX LA.gaussianElimExercise
, OMEX LA.systemWithMatrixExercise
]
-----------------------------------------------------------------------------
-- Utility functions for finding an exercise
resolveExerciseCode :: Monad m => String -> m ExerciseCode
resolveExerciseCode txt =
case findExercises (\ex -> show (exerciseCode ex) ~= txt) of
[Some ex] -> return (exerciseCode ex)
_ -> fail $ "Failed to resolve the exercise code " ++ show txt
where
s ~= t = f s == f t
f = map toLower . filter isAlphaNum
findExercises :: (forall a . Exercise a -> Bool) -> [Some Exercise]
findExercises p = [ Some e | Some e <- exerciseList, p e ]
getExercise :: Monad m => ExerciseCode -> m (Some Exercise)
getExercise code =
case findExercises ((==code) . exerciseCode) of
[hd] -> return hd
[] -> fail $ "No exercise with code " ++ show code
_ -> fail $ "Ambiguous exercise code " ++ show code
findOpenMathExercises :: (forall a . Exercise a -> Bool) -> [OpenMathExercise]
findOpenMathExercises p = [ OMEX e | OMEX e <- openMathExercises, p e ]
getOpenMathExercise :: Monad m => ExerciseCode -> m OpenMathExercise
getOpenMathExercise code =
case findOpenMathExercises ((==code) . exerciseCode) of
[hd] -> return hd
[] -> fail $ "No exercise with code " ++ show code
_ -> fail $ "Ambiguous exercise code " ++ show code