{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}

{-|
Module      : Data.Matroid.Internal
Description : 
Copyright   : (c) Immanuel Albrecht, 2020-202x
License     : BSD-3
Maintainer  : mail@immanuel-albrecht.de
Stability   : experimental
Portability : POSIX

This module provides internal helpers for the matroid package,
for instance data types that help converting different matroid
representations to Matroid . . -types.

Although it is exported, using anything from this module that is 
not re-exported by another module may (and eventually will) break 
client side code. The main reason for exporting this is so anyone
can inspect internals using haddock; it's a little bit like an
open door policy for code.

-}
module Data.Matroid.Internal
    (
        fromRk
      , namedFromRk
      , fromIndep
      , namedFromIndep
      , fromBasisFilter
      , namedFromBasisFilter
      , RkMatroid
      , IndepMatroid
      , BasisFilterMatroid
    ) where

import Data.Matroid.Typeclass 
import Data.Set (Set)

-- | we use this data type to combine a given rank function with the default implementations from the Matroid typeclass
data RkMatroid a = RkM -- ^ matroid from rank function constructor
                   String -- ^ name
                   (Set a) -- ^ ground set of the matroid
                   (Set a -> Int) -- ^ rank function
            
                   
instance Show a => Show (RkMatroid a) where
    show :: RkMatroid a -> String
show (RkM String
name Set a
_ Set a -> Int
_) = String
name 
    
instance (Ord a, Show a) => Matroid RkMatroid a where
    groundset :: RkMatroid a -> Set a
groundset (RkM String
_ Set a
e Set a -> Int
_) = Set a
e
    showName :: RkMatroid a -> String
showName (RkM String
name Set a
_ Set a -> Int
_) = String
name
    rk :: RkMatroid a -> Set a -> Int
rk (RkM String
_ Set a
_ Set a -> Int
r) = Set a -> Int
r

-- | matroid constructor given groundset and rank function
fromRk :: (Show a) => (Set a) {- ^ ground set -} -> (Set a -> Int) {- ^ rank function -} -> (RkMatroid a)
fromRk :: Set a -> (Set a -> Int) -> RkMatroid a
fromRk Set a
g = String -> Set a -> (Set a -> Int) -> RkMatroid a
forall a. String -> Set a -> (Set a -> Int) -> RkMatroid a
namedFromRk (String
"fromRk (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Set a -> String
forall a. Show a => a -> String
show Set a
g) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") (rk)") Set a
g

-- | named matroid constructor given groundset and rank function
namedFromRk :: String {- ^ name -} -> (Set a) {- ^ ground set -} -> (Set a -> Int) {- ^ rank function -} -> (RkMatroid a)
namedFromRk :: String -> Set a -> (Set a -> Int) -> RkMatroid a
namedFromRk = String -> Set a -> (Set a -> Int) -> RkMatroid a
forall a. String -> Set a -> (Set a -> Int) -> RkMatroid a
RkM 



-- | we use this data type to combine a given independence test with the default implementations from the Matroid typeclass
data IndepMatroid a = IndepM -- ^ matroid from independence-test constructor
                   String -- ^ name
                   (Set a) -- ^ ground set of the matroid
                   (Set a ->  Bool) -- ^ independence test function
            
                   
instance Show a => Show (IndepMatroid a) where
    show :: IndepMatroid a -> String
show (IndepM String
name Set a
_ Set a -> Bool
_) = String
name
    
instance (Ord a, Show a) => Matroid IndepMatroid a where
    groundset :: IndepMatroid a -> Set a
groundset (IndepM String
_ Set a
e Set a -> Bool
_) = Set a
e
    showName :: IndepMatroid a -> String
showName (IndepM String
name Set a
_ Set a -> Bool
_) = String
name
    indep :: IndepMatroid a -> Set a -> Bool
indep (IndepM String
_ Set a
_ Set a -> Bool
i) = Set a -> Bool
i
    
-- | matroid constructor given groundset and test for independence
fromIndep :: (Show a) => (Set a) {- ^ ground set -} -> (Set a -> Bool) {- ^ independence test -} -> (IndepMatroid a)
fromIndep :: Set a -> (Set a -> Bool) -> IndepMatroid a
fromIndep Set a
g = String -> Set a -> (Set a -> Bool) -> IndepMatroid a
forall a. String -> Set a -> (Set a -> Bool) -> IndepMatroid a
namedFromIndep (String
"fromIndep (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Set a -> String
forall a. Show a => a -> String
show Set a
g) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") (indep)") Set a
g 

-- | named matroid constructor given groundset and test for independence
namedFromIndep :: String  {- ^ name -} -> (Set a) {- ^ ground set -} -> (Set a -> Bool) {- ^ independence test -} -> (IndepMatroid a)
namedFromIndep :: String -> Set a -> (Set a -> Bool) -> IndepMatroid a
namedFromIndep = String -> Set a -> (Set a -> Bool) -> IndepMatroid a
forall a. String -> Set a -> (Set a -> Bool) -> IndepMatroid a
IndepM


-- | we use this data type to combine a given a basis filter with the default implementations from the Matroid typeclass
data BasisFilterMatroid a = BasisM -- ^ matroid from basis-filter constructor
                   String -- ^ name
                   (Set a) -- ^ ground set of the matroid
                   (Set a -> Set a) -- ^ function that returns a maximal independent subset of its input
            
                   
instance Show a => Show (BasisFilterMatroid a) where
    show :: BasisFilterMatroid a -> String
show (BasisM String
name Set a
_ Set a -> Set a
_) = String
name 
    
instance (Ord a,Show a) => Matroid BasisFilterMatroid a where
    groundset :: BasisFilterMatroid a -> Set a
groundset (BasisM String
_ Set a
e Set a -> Set a
_) = Set a
e
    showName :: BasisFilterMatroid a -> String
showName (BasisM String
name Set a
_ Set a -> Set a
_) = String
name
    basis :: BasisFilterMatroid a -> Set a -> Set a
basis (BasisM String
_ Set a
_ Set a -> Set a
b) = Set a -> Set a
b
    
-- | matroid constructor given groundset and set-basis filter
fromBasisFilter :: (Show a) => (Set a) {- ^ ground set -} -> (Set a -> Set a) {- ^ returns maximal independent subset -} -> (BasisFilterMatroid a)
fromBasisFilter :: Set a -> (Set a -> Set a) -> BasisFilterMatroid a
fromBasisFilter Set a
g = String -> Set a -> (Set a -> Set a) -> BasisFilterMatroid a
forall a.
String -> Set a -> (Set a -> Set a) -> BasisFilterMatroid a
namedFromBasisFilter (String
"fromBasis (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Set a -> String
forall a. Show a => a -> String
show Set a
g) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") (basis)") Set a
g

-- | named matroid constructor given groundset and set-basis filter
namedFromBasisFilter :: String {- ^ name -} -> (Set a) {- ^ ground set -} -> (Set a -> Set a) {- ^ returns maximal independent subset -} -> (BasisFilterMatroid a)
namedFromBasisFilter :: String -> Set a -> (Set a -> Set a) -> BasisFilterMatroid a
namedFromBasisFilter = String -> Set a -> (Set a -> Set a) -> BasisFilterMatroid a
forall a.
String -> Set a -> (Set a -> Set a) -> BasisFilterMatroid a
BasisM