Get number of fields for non-record ADTs using Data type class?

Dear list, Is it possible te get the number of fields for data constructors for a plain ADT, i.e something with no record fields? E.g for data T = A Int Double | B String (Maybe String) it would give 2 for both `A` and `B`. For a record it's possible using the `constrFields` function from Data.Data. I was trying to follow this tutorial by Christopher Done https://chrisdone.com/posts/data-typeable, and I feel that it must be possible somehow to get these numbers with the gmap*/gfold* functions, but the use of them is over my head at the moment. Best, -- Markus Läll

This maps every field to 1, and folds them together using (+): Data.Data.gmapQl (+) 0 (const 1) :: T -> Int (There has to be a similarly easy solution using GHC.Generics instead but I can't think of one...) Li-yao On 10/29/18 2:56 PM, Markus Läll wrote:
Dear list,
Is it possible te get the number of fields for data constructors for a plain ADT, i.e something with no record fields? E.g for
data T = A Int Double | B String (Maybe String)
it would give 2 for both `A` and `B`.
For a record it's possible using the `constrFields` function from Data.Data.
I was trying to follow this tutorial by Christopher Done https://chrisdone.com/posts/data-typeable, and I feel that it must be possible somehow to get these numbers with the gmap*/gfold* functions, but the use of them is over my head at the moment.
Best,
-- Markus Läll
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

I don't think there is a point in looking for GHC.Generics-based solution,
as Data.Data is the exact match for this kind of problem.
--
Best, Artem
On Mon, 29 Oct 2018 at 16:35 Li-yao Xia
This maps every field to 1, and folds them together using (+):
Data.Data.gmapQl (+) 0 (const 1) :: T -> Int
(There has to be a similarly easy solution using GHC.Generics instead but I can't think of one...)
Li-yao
On 10/29/18 2:56 PM, Markus Läll wrote:
Dear list,
Is it possible te get the number of fields for data constructors for a plain ADT, i.e something with no record fields? E.g for
data T = A Int Double | B String (Maybe String)
it would give 2 for both `A` and `B`.
For a record it's possible using the `constrFields` function from Data.Data.
I was trying to follow this tutorial by Christopher Done https://chrisdone.com/posts/data-typeable, and I feel that it must be possible somehow to get these numbers with the gmap*/gfold* functions, but the use of them is over my head at the moment.
Best,
-- Markus Läll
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On 10/29/18 4:42 PM, Artem Pelenitsyn wrote:
I don't think there is a point in looking for GHC.Generics-based solution, as Data.Data is the exact match for this kind of problem.
Although GHC.Generics has its shortcomings (usage complexity and compile times), I still find it worthwhile to advocate as a statically-typed alternative to the dynamically-typed Data.Data for many problems, including this one. Using the one-liner library (which is built around GHC.Generics), the equivalent line of code is: getSum . gfoldMap @AnyType (const 1) :: T -> Int Data.Data is more visible mainly because it comes with a lot of functionality baked into the standard library, whereas GHC.Generics provides only a minimal interface and we have to find everything else in separate packages. However, there is no fundamental reason why one is a better fit than the other for the task of counting constructor fields. Li-yao
On Mon, 29 Oct 2018 at 16:35 Li-yao Xia
mailto:lysxia@gmail.com> wrote: This maps every field to 1, and folds them together using (+):
Data.Data.gmapQl (+) 0 (const 1) :: T -> Int
(There has to be a similarly easy solution using GHC.Generics instead but I can't think of one...)
Li-yao
On 10/29/18 2:56 PM, Markus Läll wrote: > Dear list, > > Is it possible te get the number of fields for data constructors for a > plain ADT, i.e something with no record fields? E.g for > > data T = A Int Double | B String (Maybe String) > > it would give 2 for both `A` and `B`. > > For a record it's possible using the `constrFields` function from Data.Data. > > I was trying to follow this tutorial by Christopher Done > https://chrisdone.com/posts/data-typeable, and I feel that it must be > possible somehow to get these numbers with the gmap*/gfold* functions, > but the use of them is over my head at the moment. > > > Best, > > > > -- > Markus Läll > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. > _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Oh, didn't know about `one-liner`. This looks v. nice. Thank you!
-- Artem
On Mon, 29 Oct 2018 at 17:52 Li-yao Xia
On 10/29/18 4:42 PM, Artem Pelenitsyn wrote:
I don't think there is a point in looking for GHC.Generics-based solution, as Data.Data is the exact match for this kind of problem.
Although GHC.Generics has its shortcomings (usage complexity and compile times), I still find it worthwhile to advocate as a statically-typed alternative to the dynamically-typed Data.Data for many problems, including this one.
Using the one-liner library (which is built around GHC.Generics), the equivalent line of code is:
getSum . gfoldMap @AnyType (const 1) :: T -> Int
Data.Data is more visible mainly because it comes with a lot of functionality baked into the standard library, whereas GHC.Generics provides only a minimal interface and we have to find everything else in separate packages. However, there is no fundamental reason why one is a better fit than the other for the task of counting constructor fields.
Li-yao
On Mon, 29 Oct 2018 at 16:35 Li-yao Xia
mailto:lysxia@gmail.com> wrote: This maps every field to 1, and folds them together using (+):
Data.Data.gmapQl (+) 0 (const 1) :: T -> Int
(There has to be a similarly easy solution using GHC.Generics instead but I can't think of one...)
Li-yao
On 10/29/18 2:56 PM, Markus Läll wrote: > Dear list, > > Is it possible te get the number of fields for data constructors for a > plain ADT, i.e something with no record fields? E.g for > > data T = A Int Double | B String (Maybe String) > > it would give 2 for both `A` and `B`. > > For a record it's possible using the `constrFields` function from Data.Data. > > I was trying to follow this tutorial by Christopher Done > https://chrisdone.com/posts/data-typeable, and I feel that it must be > possible somehow to get these numbers with the gmap*/gfold* functions, > but the use of them is over my head at the moment. > > > Best, > > > > -- > Markus Läll > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. > _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Hi and thank you for the answers -- I'll use Data for now since generics
seem scary at this point.
Another question :): is there a better way to get the constructor of some
partially applied data constructor. My current solution follows (and it
works), but I'm wondering if there is a better way? The issue is that I'm
feeding `undefined`s until the constructor is saturated and then get the
Constr, but it feels like using a loophole (the existence of `undefined`)
to achieve the result.
class GetConstr a where
getConstr :: a -> Constr
instance {-# OVERLAPPING #-} (GetConstr b) => GetConstr (a -> b) where
getConstr f = getConstr (f undefined)
instance {-# OVERLAPPABLE #-} (Data a) => GetConstr a where
getConstr a = toConstr a
On Mon, Oct 29, 2018 at 11:07 PM Artem Pelenitsyn
Oh, didn't know about `one-liner`. This looks v. nice. Thank you!
-- Artem
On Mon, 29 Oct 2018 at 17:52 Li-yao Xia
wrote: On 10/29/18 4:42 PM, Artem Pelenitsyn wrote:
I don't think there is a point in looking for GHC.Generics-based solution, as Data.Data is the exact match for this kind of problem.
Although GHC.Generics has its shortcomings (usage complexity and compile times), I still find it worthwhile to advocate as a statically-typed alternative to the dynamically-typed Data.Data for many problems, including this one.
Using the one-liner library (which is built around GHC.Generics), the equivalent line of code is:
getSum . gfoldMap @AnyType (const 1) :: T -> Int
Data.Data is more visible mainly because it comes with a lot of functionality baked into the standard library, whereas GHC.Generics provides only a minimal interface and we have to find everything else in separate packages. However, there is no fundamental reason why one is a better fit than the other for the task of counting constructor fields.
Li-yao
On Mon, 29 Oct 2018 at 16:35 Li-yao Xia
mailto:lysxia@gmail.com> wrote: This maps every field to 1, and folds them together using (+):
Data.Data.gmapQl (+) 0 (const 1) :: T -> Int
(There has to be a similarly easy solution using GHC.Generics
instead
but I can't think of one...)
Li-yao
On 10/29/18 2:56 PM, Markus Läll wrote: > Dear list, > > Is it possible te get the number of fields for data constructors for a > plain ADT, i.e something with no record fields? E.g for > > data T = A Int Double | B String (Maybe String) > > it would give 2 for both `A` and `B`. > > For a record it's possible using the `constrFields` function from Data.Data. > > I was trying to follow this tutorial by Christopher Done > https://chrisdone.com/posts/data-typeable, and I feel that it must be > possible somehow to get these numbers with the gmap*/gfold* functions, > but the use of them is over my head at the moment. > > > Best, > > > > -- > Markus Läll > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. > _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Markus Läll
participants (3)
-
Artem Pelenitsyn
-
Li-yao Xia
-
Markus Läll