lundi 12 novembre 2018

freer-simple - How can I generate a list of effect members at runtime?

I am trying to create a function to generate a string representation of effects at runtime.

-- In a shared module

... definitions for TestConfig, RunConfig

data GenericTest tc rc i effs as vs = GenericTest {
  configuration :: tc,
  components :: ItemClass i vs => TestComponents rc i effs as vs
} deriving Typeable

type Test = GenericTest TestConfig RunConfig

type EFFLogger effs = Member Logger effs
type EFFFileSystem effs = Members '[Logger, Ensure, FileSystem] effs 

-- Child module 1

.... definitions for items, iterator etc 

type Effects effs = EFFFileSystem effs

test :: forall effs. Effects effs => Test Item effs ApState ValState
test = GenericTest {
              configuration = config {address = moduleOf ''ApState},
              components = TestComponents {
                                testItems = items,
                                testInteractor = interactor,
                                testPrepState = prepState
                            }
            }

-- Child module 2 (the same as module 1 but different effects)

.... definitions for items, iterator etc 

type Effects effs = EFFLogger effs

test :: forall effs. Effects effs => Test Item effs ApState ValState
test = GenericTest {
              configuration = config {address = moduleOf ''ApState},
              components = TestComponents {
                                testItems = items,
                                testInteractor = interactor,
                                testPrepState = prepState
                            }
            }

At run time I want a function f such that:

> f ChildMod1.test 
> ["Logger", "Ensure", "FileSystem"]
>
> f ChildMod2.test 
>  ["Logger"]

From repl with Child module 1 loaded I can get the following, which if I could get something similar in non-interpreted code would be enough to get me what I want:

> :t test
> test
    :: (Data.OpenUnion.Internal.FindElem Logger effs,
        Data.OpenUnion.Internal.FindElem Ensure effs,
        Data.OpenUnion.Internal.FindElem FileSystem effs) =>
       Test Item effs ApState ValState

I have tried using Typeable as suggested in the following:

How can I read the metadata of a type at runtime?

but typeOf gives me issues which I have no clue how to solve:

> typeOf test

  <interactive>:5:1-11: error:
      * No instance for (Typeable effs0) arising from a use of `typeOf'
      * In the expression: typeOf test
        In an equation for `it': it = typeOf test

  <interactive>:5:8-11: error:
      * Ambiguous type variable `effs0' arising from a use of `test'
        prevents the constraint `(Data.OpenUnion.Internal.FindElem
                                    Logger effs0)' from being solved.
        Probable fix: use a type annotation to specify what `effs0' should be.
        These potential instances exist:
          two instances involving out-of-scope types
            instance [overlappable] Data.OpenUnion.Internal.FindElem t r =>
                                    Data.OpenUnion.Internal.FindElem t (t' : r)
              -- Defined in `Data.OpenUnion.Internal'
            instance Data.OpenUnion.Internal.FindElem t (t : r)
              -- Defined in `Data.OpenUnion.Internal'
      * In the first argument of `typeOf', namely `test'
        In the expression: typeOf test
        In an equation for `it': it = typeOf test





Aucun commentaire:

Enregistrer un commentaire