module Data.Loop
    ( module Data.Quasigroup
    , module Data.Unital
    , Loop (..)
    ) where

import Control.Applicative
import Data.Quasigroup (Quasigroup (..))
import Data.Unital

-- | A 'Loop' is a 'Quasigroup' with an identity element. Both 'invl'
--   and 'invr' have default definitions, but if you specialize 'invl'
--   or 'invr', they must satisfy the following properties:
--
--   > invl l + l  ==  zero
--   > l + invr l  ==  zero
class (Quasigroup l, Unital l) => Loop l where
    -- | Left inverse
    invl :: l -> l
    invl = (`leftDivide` unit)

    -- | Right inverse
    invr :: l -> l
    invr = rightDivide unit

instance Loop b => Loop (a -> b) where
    invl = map invl
    invr = map invr
