TheMADMAN
TheMADMAN

Reputation: 319

proper use of class and types

I am currently working on a project that is related to physics. I want to improve my already working program and give it more structure. But at the moment I am going in circles and not making progress.

I want to build green's functions, but I also want to be very general, so that I can reuse my library, of course.

I would like to have a class that holds the green's function based on the problem, this can be free space, or a resonator or something else. And the functions also depend on the gauge. In gauge 1 I get a representation of green's function like this:

greenF_Gauge1 :: (Scalar a -> a) -> (Scalar a -> a) -> Scalar a -> Scalar a -> Scalar a

But in Gauge 2 I have one argument more and a different return type

greenF_Gauge2 :: (Scalar a -> a) -> (Scalar a -> a) -> Scalar a -> Scalar a -> Scalar a -> Scalar a -> Complex (Scalar a)

It would be nice to have only one function for the green's function and just select the correct one by the type of the Gauge. And building on that I want to create the correct function based on the nature of the problem (free space etc.) Since I have different numbers of arguments and different return types I somehow failed at the class definition.

I tried:

type GreenFC a =  ((Scalar a -> a) -> (Scalar a -> a)  -> Scalar a -> Scalar a -> Scalar a)
type GreenFL a =  ((Scalar a -> a) -> (Scalar a -> a)  -> Scalar a -> Scalar a -> Scalar a -> Complex (Scalar a))
type GreenMix a = (GreenFC a, GreenFL a)
data ResultType a  = Clomb (GreenFC a) | Lrenz (GreenFL a) | Mix (GreenMix a)

class  (VectorSpace a) => GreenFunc g a  where
  greenF :: g -> ResultType a 

But when constructing the actual functions based on my structure, I have a problem accessing the return values, which are functions hidden in ResultType. I think there must be a more elegant way to do this.

I would like to use the power of the type system and make the whole program more abstract, so that I can exchange the gauge for example and don't have to hack in my code. But currently my level of understanding is that I know about type families etc but I still don't know how to apply them properly. Any hints in that direction are very much appreciated.

Upvotes: 2

Views: 118

Answers (2)

viorior
viorior

Reputation: 1803

There is a problem with different number of arguments.

The simplest way is to use data type for "parameters". And to use data type for "result".

And to use just pattern-matching instead of class.

Something like that:

type GreenMix a = (Scalar a, Complex (Scalar a))
data ResultType a  = Clomb (Scalar a) 
                   | Lrenz (Complex (Scalar a)) 
                   | Mix (GreenMix a)

data Gauge a = Gauge1 (Scalar a) (Scalar a)
             | Gauge2 (Scalar a) (Scalar a) (Scalar a)

greenF :: (Scalar a -> a) -> (Scalar a -> a) -> Gauge a -> Result a
greenF f1 f2 (Gauge1 g1 g2)    = Clomb $ greenF_Gauge1 f1 f2 g1 g2
greenF f1 f2 (Gauge2 g1 g2 g3) = Lrenz $ greenF_Gauge2 f1 f2 g1 g2 g3

Upvotes: 1

leftaroundabout
leftaroundabout

Reputation: 120751

Honestly I don't know if this makes any sense physically, but looking at your code I'd be tempted to do something like the following:

{-# LANGUAGE TypeFamilies #-}

data GreenParamFC a = GreenParamFC {
       gpFC_f1, gpFC_f2 :: Scalar a -> a
     , gpFC_s1, gpFC_s2 :: Scalar a
     }
data GreenParamFL a = GreenParamFL {
       gpFL_f1, gpFL_f2 :: Scalar a -> a
     , gpFL_s1, gpFL_s2, gpFL_s3 :: Scalar a
     }
data GreenMixParam a = GreenMix {
       gm_FC :: GreenParamFC a
     , gm_FL :: GreenParamFL a
     }

class GreenParams p where
  type GreenResult p a :: *
  greenF :: p a -> GreenResult p a

instance GreenParams GreenParamFC where
  type GreenResult GreenParamFC a = Scalar a
  greenF (GreenParamFC f1 f2 s1 s2) = ...

instance GreenParams GreenParamFL where
  type GreenResult GreenParamFL a = Complex (Scalar a)
  greenF (GreenParamFL f1 f2 s1 s2 s3) = ...

instance GreenParams GreenMixParam where
  type GreenResult GreenMixParam a = (Scalar a, Complex (Scalar a))
  greenF (GreenMix
              (GreenParamFC f1 f2 s1 s2)
              (GreenParamFL f1 f2 s1 s2 s3)
         ) = (..., ...)

Upvotes: 1

Related Questions