purescript-contrib/purescript-uri

Generic lenses

Opened this issue · 5 comments

Looking at #30

There is a couple of suggestions

Type classes for lenses

class HasScheme a where 
  _scheme :: ALens' a (Maybe Scheme)

Using records instead

type AbsoluteURI = 
  { scheme :: Maybe Scheme 
  , query :: Maybe Query 
  , hiePart :: HierarchicalPart 
  } 

_scheme :: forall r a. Lens' { scheme :: a |r } a 
_scheme = lens _.scheme _{ scheme = _ }

Using newtype around records

newtype AbsoluteURI = AbsoluteURI
  { scheme :: Maybe Scheme 
  ... } 

derive instance newtypeAbsoluteURI :: Newtype AbsoluteURI _ 

_scheme :: forall r n a rr. Newtype n r => RowCons "scheme" a r rr => Lens' n a 
_scheme = _Newtype <<< prop "scheme"

@garyb @kritzcreek What do you think? I think the 3rd one preserves both typesafety and polymorphic behaviour w/o introducing new entities.

garyb commented

Yeah, I did consider switching to newtypes-of-records when I was working on this but I didn't want to break the API yet again just now.

I'd probably just have _AbsoluteURI = _Newtype, etc. lenses then, and let them be composed with a general _scheme.

Oh! I see the differences between approaches. If there is generic lens from newtype to query type that effectively means that all uris have the same implicit type. And when there is _AbsoluteURI that means that those things are different entities with different types.

That's another question: why uri can't be implemented as pathy using phantoms? I mean phantoms around newtyped records.

garyb commented

The URI type variations have more differences than just the path type - some aren't allowed to have query/fragment, etc. All the stuff in here is based on the spec, so the encoding isn't always as natural as it might be, as I was trying to ensure validity in construction (which as it happens isn't right anyway, you can still construct invalid URIs directly if you really try).

garyb commented

The newtype/record approach didn't happen in the end as some more sum components were introduced that made it awkward, but we could still perhaps do something with the class approach for this if it's perceived to be painful enough still 😉

Is there still any desire for this? #50 re-introduces the newtype/record approach, by the way.