[Haskell-cafe] Deriving with generics without values

Roman Cheplyaka roma at ro-che.info
Sun Jul 14 17:21:58 CEST 2013


Hi,

(Redirecting this back to cafe to keep it discoverable — hope you don't
mind.)

* JP Moresmau <jpmoresmau at gmail.com> [2013-07-14 16:02:56+0200]
> Hello, sorry to bother you after you've been kind enough to answer me on
> the list! I've looked a the smallcheck code but I don't see how to apply it
> to my issue. First of all, I can't find the definition of >>- that you use
> for example in <~>. I suppose I'm doing something silly...

That comes from LogicT. >>- is almost the same as >>=, and <~> is almost
the same as <*>. Byt that's not relevant to the generic aspect of the
code.

> But then, if I understand the code, the instances for GSerial rebuild
> a type definition that mimicks the one passed as type argument, using
> the final values (under the K1s) to generate a series. But in my case,
> I want to be able to extract information from the original type, I'm
> not just interested in the final value. What I want to be able is to
> extract for example the constructor name and do something with it. I
> don't see how to achieve that with your system.

Yes, it doesn't do everything that you want to do, but it shows the
idea.

The information you need is all there — for example, to get the
constructor name, you need to get hold of the C1 type (which is a
synonym for M1 C), and then call the conName method.

Lest you get lost in all this, it is useful to visualize the generic
representation by running your code through -ddump-deriv. Here's an
example:

    % ghci -XDeriveGeneric -ddump-deriv -dsuppress-module-prefixes
    Prelude GHC.Generics> data T a = A { a :: a } | B | C deriving Generic

    ==================== Derived instances ====================
    Derived instances:
      instance Generic (T a_ao7) where
        from (A g1_aph) = M1 (L1 (M1 (M1 (K1 g1_aph))))
        from B = M1 (R1 (L1 (M1 U1)))
        from C = M1 (R1 (R1 (M1 U1)))
        to (M1 (L1 (M1 (M1 (K1 g1_api))))) = A g1_api
        to (M1 (R1 (L1 (M1 U1)))) = B
        to (M1 (R1 (R1 (M1 U1)))) = C
      
      instance Datatype D1T where
        datatypeName _ = "T"
        moduleName _ = ":Interactive"
      
      instance Constructor C1_0T where
        conName _ = "A"
        conIsRecord _ = True
      
      instance Constructor C1_1T where conName _ = "B"
      
      instance Constructor C1_2T where conName _ = "C"
      
      instance Selector S1_0_0T where selName _ = "a"
      

    Generic representation:
      
      Generated datatypes for meta-information:
        D1T
        C1_0T
        C1_1T
        C1_2T
        S1_0_0T
      
      Representation types:
        type Rep (T a_ao7) = D1
                               D1T
                               (C1 C1_0T (S1 S1_0_0T (Rec0 a_ao7))
                                :+: (C1 C1_1T U1 :+: C1 C1_2T U1))

This should give you an idea about how the structure you're dealing with
looks like, and where the important information resides.

> I've also look at Aeson with the generic JSON parsing, but that's
> using SYB which is again different, and SYB doesn't seem to provide
> the types of the constructor fields, which I would need too...

It provides the types of the constructor fields through the Typeable
class, which may or may not be sufficient for your needs... Anyway,
you're right in that it is a completely different approach.

Roman

> On Fri, Jul 12, 2013 at 10:57 AM, Roman Cheplyaka <roma at ro-che.info> wrote:
> 
> > Well, in your case, you need not 'from', but 'to', in order to convert
> > from a generic representation to yours.
> >
> > Take a look at how a similar task is done in SmallCheck:
> >
> > https://github.com/feuerbach/smallcheck/blob/master/Test/SmallCheck/Series.hs#L180
> >
> > https://github.com/feuerbach/smallcheck/blob/master/Test/SmallCheck/Series.hs#L352
> >
> > Roman
> >
> > * JP Moresmau <jpmoresmau at gmail.com> [2013-07-12 10:45:39+0200]
> > > Hello all,
> > > My problem is the following: I have my own data types, and I'd like to
> > > derive automatically instances of some type class from them. I've started
> > > looking at GHC.Generics, which offer tools to do exactly that. However,
> > > some functions of my typeclass do not take my data type as a parameter,
> > but
> > > as a result. Basically:
> > >  class MyClass where
> > >    fromString :: String -> a
> > >
> > >  data MyData=MkMyData {
> > >    myField ::Int
> > >  } deriving (Generic)
> > >
> > > and I want to automatically generate the instance instance MyClass
> > MyData,
> > > using default methods, etc.
> > > The GHC Generic class does say that it uses a from function that convert
> > > from the datatype to its representation: from :: a ->
> > > Rep<
> > http://www.haskell.org/ghc/docs/7.4.1/html/libraries/ghc-prim-0.2.0.0/GHC-Generics.html#t:Rep
> > >
> > > a
> > > xfrom :: a -> Rep<
> > http://www.haskell.org/ghc/docs/7.4.1/html/libraries/ghc-prim-0.2.0.0/GHC-Generics.html#t:Rep
> > >
> > > a
> > > x
> > > But I don't have a "a" to start from! I see from the related papers that
> > > the automatically generated code from from actually does pattern matches
> > on
> > > constructors, so I need a value, undefined won't work. However I see the
> > > GHC.Generics also provide :+: (Sums: encode choice between constructors).
> > > If I have to provide an value, then the choice between constructor has
> > been
> > > done! The examples about generics on
> > > http://www.haskell.org/haskellwiki/GHC.Generics do provide an example of
> > > defining the instance for :+: but I don't understand how we can get
> > there.
> > > If I have a class method that takes a value as a parameter, and I pass
> > > undefined to it, the code will crash, since it can't pattern match on
> > > undefined.
> > >
> > > Can somebody shed some light on this? Am I using the wrong tool for the
> > > job? How can I achieve what I want? I want the full type representation
> > > with sums, but without a value to start from.
> > >
> > > Thanks a million!
> > >
> > > JP
> > > --
> > > JP Moresmau
> > > http://jpmoresmau.blogspot.com/
> >
> > > _______________________________________________
> > > Haskell-Cafe mailing list
> > > Haskell-Cafe at haskell.org
> > > http://www.haskell.org/mailman/listinfo/haskell-cafe
> >
> >
> 
> 
> -- 
> JP Moresmau
> http://jpmoresmau.blogspot.com/




More information about the Haskell-Cafe mailing list