module Calculator.Prim.Function ( Function , apply , mkFunc , mkFuncEither , oneArg , partial ) where -------------------------------------------------------------------------------- -- | Represents a function, where rank == No. of arguments data Function a = Function { arity :: Int , apply :: [a] -> Either [String] a } -------------------------------------------------------------------------------- -- | Make a @Function@ out of an arity and another function mkFunc :: Int -> ([a] -> a) -> Function a mkFunc a f = mkFuncEither a (Right . f) -------------------------------------------------------------------------------- -- | Make a @Function@ with an arity using an error giving function mkFuncEither :: Int -> ([a] -> Either [String] a) -> Function a mkFuncEither a f = Function { arity = a , apply = g } where g xs = if length xs == a then f xs else Left $ [ "Invalid no. of arguments" , "Required: " ++ show a , "Provided: " ++ show (length xs) ] -------------------------------------------------------------------------------- -- | Make a @Function@ out of a single argument function oneArg :: (a -> a) -> Function a oneArg f = mkFunc 1 (\ [x] -> f x) -------------------------------------------------------------------------------- -- | Partially apply a function, thus creating a one-argument function. -- To be used for parametrized functions, e.g getting g(x) = f(x,1,2) -- this retains the free-variable 'x' partial :: Function a -> [a] -> a -> Maybe a partial f xs x = case apply f (x:xs) of Left _ -> Nothing Right v -> Just v --------------------------------------------------------------------------------