purescript / purescript-prelude

The PureScript Prelude
BSD 3-Clause "New" or "Revised" License
163 stars 88 forks source link

Replace polymorphic proxy workaround with monomorphic Proxy type #281

Closed JordanMartinez closed 2 years ago

JordanMartinez commented 2 years ago

Description of the change

Fixes #231 by changing forall proxy. proxy SomeKind -> .. to just Proxy SomeKind.

Also removes Proxy2 and Proxy3 types since Proxy is enough now.


Checklist:

garyb commented 2 years ago

Is there a downside to leaving proxy polymorphic?

JordanMartinez commented 2 years ago

I'm not sure. I suppose one could do something like

data MyProxyType (sym :: Symbol) = MyProxyType OtherInfo

reflectSymbol (MyProxyType "foo" :: MyProxyType "bar")

But if this is hard-coded to Proxy, I don't think it would cause problems either.

thomashoneyman commented 2 years ago

Is there a downside to leaving proxy polymorphic?

What about the opposite — is there an advantage to leaving it polymorphic? As far as I remember it was a stopgap to reduce breakage but the plan was to remove it.

The main thing that comes to mind is that leaving it polymorphic is a little less clear than an explicit Proxy argument (to me), including in type errors. As a consequence we have things like Proxy2 or Proxy3, which really aren’t necessary anymore (right?).

garyb commented 2 years ago

The hypothetical advantage is you could use types other than proxy that carry the symbol... like, say you have a generic Id type that uses a symbol for discriminating between different entities:

newtype Id (tag ∷ Symbol) = Id NonEmptyString

type ItemId = Id "Item"
type OrderId = Id "Order"

You could just pass your ItemId or OrderId to places that currently expect proxy sym:

printIdType ∷ ∀ tag. IsSymbol tag ⇒ Id tag → String
printIdType = reflectSymbol

But it's not really that big a deal either, it should always be possible to instantiate a Proxy with the appropriate type anyway:

printIdType ∷ ∀ tag. IsSymbol tag ⇒ Id tag → String
printIdType _ = reflectSymbol (Proxy ∷ _ tag)

At the worst it would require adding some type signatures. Also "constructing" a Proxy is just a value dereference at runtime, the same as passing the Id _ value here, so if we think it's better for understandability purposes to make it monomorphic then I think that's fine.

I do actually have some types like Id here, but when I checked I found I'm always using Proxy anyway due to the way things worked out. :smile: