Closed expipiplus1 closed 8 years ago
On Sun, Nov 13, 2016 at 12:58:30PM -0800, Joe Hermaszewski wrote:
type BookMaybe = Book' (Maybe Text) (Maybe Text) (Maybe Text) sequenceBook :: BookMaybe -> Maybe Book sequenceBook (Book c1 c2 c3) = Book <$> c1 <*> c2 <*> pure c3
This would certainly be useful when
Book
is on the right of a left join.cc @tomjaguarpaw: Is this a sensible way of dealing with products of nullable columns? As far as I can tell the machinery in product-profunctors isn't quite adequate due to the fact that
Nothing
is a valid value forbookBlurb
and the conversion fromBookMaybe
shouldn't return Nothing because of that.
Hi Joe, could you explain more about what you mean about products of nullable columns? I don't quite understand.
@tomjaguarpaw The type synonym BookNullableColumns
in the first post is an example of this.
A use case might be in performing a left join between tables A and B. It seems quite handy to be able to end up with [(ThingA, Maybe ThingB)]
after running the query. The query itself could return [(ThingA, ThingBMaybe)]
and sequenceThingB
seems to fill the gap here.
Have you seen the new FunctionalJoin
module? It's a more sane approach to outer joins.
https://www.stackage.org/haddock/nightly-2016-11-09/opaleye-0.5.2.1/Opaleye-FunctionalJoin.html
Yeah, I was trying to coerce that into doing what I want earlier today. It's certainly an improvement on leftJoin
. Please correct me if I'm wrong, but I don't think it's possible to have this (or something equivalent) columnsResult ~ (columnsL, Maybe columnsR)
.
It's not possible at all in Opaleye, for good reason. The constructor of the Maybe
must be statically known at Query
run time so can't possibly depend on the inputs to the left join.
I thought that might be the case. Looking forward to the monadic interface ;-)
It's not possible for any interface where Query
is a functor, otherwises you could map over the constructor of the Maybe
and get a query result that depends on a Haskell function.
;-)
;-)
Oh, ;-)
Returning to this:
BookMaybe -> Maybe Book
data P a b = P (a -> Maybe b)
is an instance of ProductProfunctor
, and then
instance Default P (Maybe a) a where
def = id
gives you sequenceBook = def
.
(which, of course, generalises to all Applicative
s)
You may also want
instance Default P (Maybe a) (Maybe a) where
def = pure
depending on your application.
@tomjaguarpaw I assume you mean
instance Default P (Maybe a) a where
def = P id
instance Default P (Maybe a) (Maybe a) where
def = P pure
sequenceJobset :: JobsetMaybe -> Maybe Jobset
sequenceJobset = unP def
I neglected Default
when looking for a product-profunctors solution to this. It's certainly nicer than expanding to long applications of <*>
.
There's probably still a case to be made for the sequence*
functions being around as the type inference around leftJoin
and def
is (understandably) terrible :)
Also sequence
perhaps isn't the best name for this, suggestions welcome.
Indeed, that's what I mean.
If you want the function for it's type signature I guess that's fine but you may as well use product-profunctors for the function body.
@expipiplus1 Reviewing this now, I feel like this is a useful addition, so would like to merge it. Do you want to change the function body implementation per Toms feedback, perhaps that would further reduce clutter a little bit?
I also intend to (at some point) add another flag to allow enabling/disabling generating the NullableColumn stuff, it's not always relevant so could include this there as well then.
As for naming, since we have BookReadColumns
associated with Book
perhaps a more natural dual to BookNullableColumns
is NullableBook
instead of BookMaybe
?
Then you could call the function that turns a NullableBook
into a Maybe Book
something like fromNullableBook
, maybeBook
or something more "natural" like that?
If you want to make any of these changes, please feel free, if not I will merge anyway and let someone else with a stronger opinion than me change it to what they want :)
@folsen all those suggestions sounds good, I'll see about getting them done today.
Would BookNullable
be ok?
I'm not totally sure about the name NullableBook
as it would be nice to keep Book
as a prefix. On the other hand it'd be nice to keep fromNullable
as a prefix to all the conversion functions.
Yeah, all the other type synoms start with Book I suppose so it would make sense that that one would as well. I have no strong opinion either way, so do what you feel is best!
I also intend to (at some point) add another flag to allow enabling/disabling generating the NullableColumn stuff
By the way, I'm really hoping to move away from NullableColumn
stuff now that FunctionalJoin
exists.
Take for example the type
The result of a query returning
BookReadColumns
isBook
, however there is no type synonym for the value of a query returningBookNullableColumns
.It would be great to also have this synonym and function.
This would certainly be useful when
Book
is on the right of a left join.@tomjaguarpaw: Is this a sensible way of dealing with products of nullable columns? As far as I can tell the machinery in product-profunctors isn't quite adequate due to the fact that
Nothing
is a valid value forbookBlurb
and the conversion fromBookMaybe
shouldn't return Nothing because of that.