Hi all,
<probably_unnnecesary_background> I'm writing a Hardware-oriented DSL deep-embedded in Haskell (similar to Lava, for those familiar with it). One of the goals of the language is to support polymorphic signals (i.e. we would like to allow signals to carry values of any type, including user-defined types) The embedded compiler has different backends: simulation, VHDL, graphical representation in GraphML ... The simulation backend manages to support polymorphic signals by forcing them to be Typeable. In that way, circuit functions, no matter what signals they process, can be transformed to Dynamic and included in the AST for later simulation. The situation is more complicated for the VHDL backend. The Typeable trick works just fine for translating a limited set of predefined types (e.g. tuples) but not for user-defined types, since the embedded-compiler doesn't have access to the user-defined type declarations. One possible solution to access the type-definition of signal values would be constraining them to instances of Data. Then, we could use dataTypeOf to get access to the type representation. (Another option would be using template Haskell's reify, but I would like to avoid that by now) It would certainly be difficult map any Haskell type to VHDL, so, by now we would be content to map enumerate algebraic types (i.e. algebraic types whose all data constructors have arity zero, e.g. data Colors = Green | Blue | Red) </probably_unnnecesary_background> So, the question is. Is there a way to figure out the arity of data constructors using Data.Generics ? I'm totally new to generics, but (tell me if I'm wrong) it seems that Constr doesn't hold any information about the data-constructor arguments. Why is it so? Do you think there is a workoaround for this problem? (maybe using some other function from Data.Generics different to dataTypeOf?) Thanks in advance, Alfonso Acosta _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
On Tue, May 6, 2008 at 12:34 PM, Alfonso Acosta
<[hidden email]> wrote: | So, the question is. Is there a way to figure out the arity of data | constructors using Data.Generics ? | I'm totally new to generics, but (tell me if I'm wrong) it seems that | Constr doesn't hold any information about the data-constructor | arguments. Why is it so? Hmrmm, Playing around with it, I was able to abuse gunfold and the reader comonad to answer the problem : fst $ (gunfold (\(i,_) -> (i+1,undefined)) (\r -> (0,r)) (toConstr "Hello") :: (Int,String)) returns 2, the arity of (:), the outermost constructor in "Hello" A longer version which does not depend on undefined would be to take and define a functor that discarded its contents like: > module Args where > import Data.Generics > newtype Args a = Args { runArgs :: Int } deriving (Read,Show) > tick :: Args (b -> r) -> Args r > tick (Args i) = Args (i + 1) > tock = const (Args 0) > argsInCons = runArgs $ (gunfold tick tock (toConstr "Hello") :: (Args String) Basically all I do is rely on the fact that gunfold takes the 'tick' argument and calls it repeatedly for each argument after a 'tock' base case. The use of the reader comonad or functor is to give gunfold a 'functor-like' argument to meet its type signature. -Edward Kmett _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
Thanks a lot for your answer, it was exactly what I was looking for.
Just for the record, based on your solution I can now easily code a function to check if a Data value belongs to an enumerated algebraic type (as I defined it in my first mail). {-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables #-} import Data.Generics newtype Arity a = Arity Int deriving (Show, Eq) consArity :: Data a => Constr -> Arity a consArity = gunfold (\(Arity n) -> Arity (n+1)) (\_ -> Arity 0) belongs2EnumAlg :: forall a . Data a => a -> Bool belongs2EnumAlg a = case (dataTypeRep.dataTypeOf) a of AlgRep cons -> all (\c -> consArity c == ((Arity 0) :: Arity a )) cons _ -> False -- tests data Colors = Blue | Green | Red deriving (Data, Typeable) test1 = belongs2EnumAlg 'a' -- False test2 = belongs2EnumAlg Red -- True test3 = belongs2EnumAlg "a" -- False On Tue, May 6, 2008 at 7:42 PM, Edward Kmett <[hidden email]> wrote: > > On Tue, May 6, 2008 at 12:34 PM, Alfonso Acosta > <[hidden email]> wrote: > > | So, the question is. Is there a way to figure out the arity of data > | constructors using Data.Generics ? > > | I'm totally new to generics, but (tell me if I'm wrong) it seems that > | Constr doesn't hold any information about the data-constructor > | arguments. Why is it so? > > > Hmrmm, > > Playing around with it, I was able to abuse gunfold and the reader > comonad to answer the problem : > > fst $ (gunfold (\(i,_) -> (i+1,undefined)) (\r -> (0,r)) (toConstr > "Hello") :: (Int,String)) > > returns 2, the arity of (:), the outermost constructor in "Hello" > > A longer version which does not depend on undefined would be to take > and define a functor that discarded its contents like: > > > module Args where > > > import Data.Generics > > > newtype Args a = Args { runArgs :: Int } deriving (Read,Show) > > > tick :: Args (b -> r) -> Args r > > tick (Args i) = Args (i + 1) > > > tock = const (Args 0) > > > argsInCons = runArgs $ (gunfold tick tock (toConstr "Hello") :: (Args String) > > Basically all I do is rely on the fact that gunfold takes the 'tick' > argument and calls it repeatedly for each argument after a 'tock' base > case. > > The use of the reader comonad or functor is to give gunfold a > 'functor-like' argument to meet its type signature. > > -Edward Kmett > _______________________________________________ > Haskell-Cafe mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/haskell-cafe > Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Bugzilla from alfonso.acosta@gmail.com
Alfonso Acosta wrote:
> It would certainly be difficult map any Haskell type to VHDL, so, by > now we would be content to map enumerate algebraic types (i.e. > algebraic types whose all data constructors have arity zero, e.g. > data Colors = Green | Blue | Red) Wouldn't it be much simpler to use the standard deriveable classes Bounded and Enum, instead of an admittedly very clever trick using Data? Metaprogramming comes in many shapes and sizes, and even the humble deriving (Show,Enum,Bounded,Ord,Eq) gives you quite some leverage.. Jules _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
On Wed, May 7, 2008 at 7:47 AM, Jules Bean <[hidden email]> wrote:
> Alfonso Acosta wrote: > > > It would certainly be difficult map any Haskell type to VHDL, so, by > > now we would be content to map enumerate algebraic types (i.e. > > algebraic types whose all data constructors have arity zero, e.g. > > data Colors = Green | Blue | Red) > > > > Wouldn't it be much simpler to use the standard deriveable classes Bounded > and Enum, instead of an admittedly very clever trick using Data? No, for the reasons explained in the probably_unnnecesary_background I don't see how those instantiations would help. _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
Free forum by Nabble | Edit this page |