packages feed

calculator-0.2.0.0: src/Calculator/Prim/Function.hs

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

--------------------------------------------------------------------------------