purescript-newtype icon indicating copy to clipboard operation
purescript-newtype copied to clipboard

add unwrapF and unF

Open safareli opened this issue 7 years ago • 17 comments

fixes #10

safareli avatar Feb 12 '18 11:02 safareli

This came up in slack just now. I mentioned that Invariant (imap unwrap wrap) might make more sense as the constraint because this is still applicable to contravariant functors. But having said that; we rarely seem to use Invariant, so perhaps having multiple declarations would be better - one for Functor and one for Contravariant?

LiamGoodacre avatar Mar 16 '18 20:03 LiamGoodacre

I see this unwrapF useful for structures which contain multiple values: Array, List, some other Tree structures, as otherwise you would need to iterate on all values and apply id to each of them.

All this are Functors. As I understand most Contravariant functors have a function underneath so f a "consumes" values of type a and usually they consume just one a so it's not that costly to cmap unwrap when you are going to run the unwrap on one value. I might be missing something tho, but if not, it means the unwrap specialized for Contravariant will be not that useful.

If you think it's worth adding tho what you think about the names? are this fine: unwrapCF and unCF ?

safareli avatar Mar 17 '18 14:03 safareli

Since we're implementing this as a straight coerce, we could drop the constraint entirely too?

garyb avatar Apr 12 '18 11:04 garyb

If we drop the constraint than it might be unsafe

safareli avatar Apr 12 '18 12:04 safareli

How would it be unsafe?

LiamGoodacre avatar Apr 13 '18 13:04 LiamGoodacre

Yes, it actually seems to be safe even for contravention functions

safareli avatar Jun 20 '18 07:06 safareli

There is no telling what a parameter is used for in the general case. Many libraries use unsafeCoerce themselves under the guard of carefully constructed types. The existence of wrapF and unwrapF without the Functor constraint means anyone can reach inside any type and wreak havoc.

eric-corumdigital avatar Feb 20 '19 19:02 eric-corumdigital

@eric-corumdigital there is wrap defined as part of class Newtype, but there is nowrapF. this pr is proposing addition of unwrapF an unF (note this functions have Newtype constraint). It should work fine for bot functors and contravariant functors. Can you point out some example where current definition of unWrapF can cause some issues?

safareli avatar Feb 21 '19 10:02 safareli

Yes, it works fine for Functors, but wrapF and unwrapF are not constrained to Functor, which is why there is a problem.

eric-corumdigital avatar Feb 22 '19 21:02 eric-corumdigital

.... which is why there is a problem.

But what exactly is a problem? Can you point out some concrete example where the problems of unWrapF (as it's defined now) are ilustrated?

safareli avatar Feb 25 '19 11:02 safareli

@safareli Data.Set.Set.

eric-corumdigital avatar Mar 15 '19 17:03 eric-corumdigital

Now that we have safe coercions we could, in the spirit of https://github.com/purescript/purescript-newtype/pull/22, constrain unwrapF and unF with Coercible (f t) (f a) instead of Functor f and support both covariant and contravariant functors!

This would make the Newtype t a constraint redundant but we probably want to keep it to aid inference. Ideally we would have a Representational f constraint (given type Representational f = forall a b. Coercible (f a) (f b)) instead of Coercible (f t) (f a) but this requires constraint kinds and quantified constraints, we’re not there yet.

kl0tl avatar Nov 26 '20 17:11 kl0tl

#22 was merged, so this can move forward.

JordanMartinez avatar Dec 27 '20 03:12 JordanMartinez

Is this needed now that we have Coercible? I’d suggest letting people use coerce directly and being done with it.

hdgarrood avatar Dec 27 '20 03:12 hdgarrood

Those functions could benefit from the functional dependency brought by the Newtype constraint, I’d be inclined to revisit this after 0.14 though: perhaps bare coerce will be enough for most cases and perhaps we’ll discover more helpful combinators for the rest.

kl0tl avatar Dec 27 '20 15:12 kl0tl

I've addressed the merge conflict. Are we still interested in adding this?

JordanMartinez avatar Sep 22 '21 04:09 JordanMartinez

CI is now failing with:

[1/1 NoInstanceFound] src/Data/Newtype.purs:62:11

  62  unwrapF = coerce
                ^^^^^^
  
  No type class instance was found for
  
    Prim.Coerce.Coercible (f0 t1)
                          (f0 a2)
  
  while checking that type forall (a :: Type) (b :: Type). Coercible @Type a b => a -> b
    is at least as general as type f0 t1 -> f0 a2
  while checking that expression coerce
    has type f0 t1 -> f0 a2
  in value declaration unwrapF
  
  where f0 is a rigid type variable
          bound at (line 62, column 11 - line 62, column 17)
        t1 is a rigid type variable
          bound at (line 62, column 11 - line 62, column 17)
        a2 is a rigid type variable
          bound at (line 62, column 11 - line 62, column 17)

           Src   Lib   All
Warnings   0     0     0  
Errors     1     0     1  

JordanMartinez avatar Sep 23 '21 14:09 JordanMartinez