Skip to content

[generics-rep] No instance for Unit? #242

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
athanclark opened this issue Nov 3, 2018 · 5 comments
Closed

[generics-rep] No instance for Unit? #242

athanclark opened this issue Nov 3, 2018 · 5 comments

Comments

@athanclark
Copy link

Why isn't there a Generic Unit rep instance? Is it because there's no data constructors? If so, why would it not be technically trivial to generate a value of Unit given the fact that one exists? I'm not sure if I follow the technical reasoning why there isn't an instance, but I could see it because of how weird Unit is for purescript.

@garyb
Copy link
Member

garyb commented Nov 11, 2018

I don't know why there isn't an instance here - it could be because of the Unit representation, but I'm not sure if that matters so much with -generic-rep. Maybe someone else knows better?

I assume the instance would be

instance genericUnitGeneric Unit (Constructor "Unit" NoArguments) where
  to _ = unit
  from _ = Constructor NoArguments

@athanclark
Copy link
Author

athanclark commented Sep 30, 2019

This is probably asked a lot too - but why stop at Unit? Why not also have instances for all elementary types? Is it because it's supposed to only represent the structure of algebraic data types? I feel like there could pretty easily be constants for supporting types like Int etc:

data GenericInt = GenericInt Int

instance genericInt :: Generic Int GenericInt where
  to (GenericInt x) = x
  from x = GenericInt x

instance genericShowGenericInt :: GenericShow GenericInt where
  genericShow' (GenericInt x) = show x

Now if I make my own fancy type deriving generic:

data Foo a = Bar | Baz a
derive instance genericFoo :: Generic a a' => Generic (Foo a) _
instance showFoo :: (Show a, Generic a a') => Show (Foo a) where
  show = genericShow

then this wouldn't cause a type error:

show (Foo 1) -- "Foo 1"

@hdgarrood
Copy link
Contributor

That's not really how Generic is meant to be used. Unlike the previous (now-deprecated) Generic class from purescript-generics, this one is intended to only 'peel off' one layer of your data type, so that you aren't locked in to using Generic all the way down your entire data structure. So when you use it, you're supposed to use it together with type classes which have instances for the 'leaves' of your data types already.

See for example the EncodeRep and EncodeRepArgs classes in argonaut-generic: https://pursuit.purescript.org/packages/purescript-argonaut-generic/5.0.0/docs/Data.Argonaut.Encode.Generic.Rep

EncodeRep delegates to EncodeRepArgs for arguments of data constructors; see the instance (IsSymbol name, EncodeRepArgs a) => EncodeRep (Constructor name a). Then, EncodeRepArgs itself delegates to the standard EncodeJson class for data constructor arguments; see the instance (EncodeJson a) => EncodeRepArgs (Argument a).

I suspect that in your case, the issue is the constraint on your genericFoo instance. You should just write:

data Foo a = Bar | Baz a
derive instance genericFoo :: Generic (Foo a) _
instance showFoo :: (Show a) => Show (Foo a) where
  show = genericShow

@JordanMartinez JordanMartinez changed the title No instance for Unit? [generics-rep] No instance for Unit? Dec 26, 2020
@JordanMartinez JordanMartinez transferred this issue from purescript-deprecated/purescript-generics-rep Dec 26, 2020
@JordanMartinez
Copy link
Contributor

Should this issue be closed?

@hdgarrood
Copy link
Contributor

Yes, I think so.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants