Open theNerd247 opened 4 years ago
A simple solution would be to get rid of Af
and use coerce
instead of the newtype
package anywho. Instead I can use a custom newtype whos Semigroup instance handles the logic of randomly selecting between 2 randomly possibly selected values.
https://github.com/theNerd247/optparse-repline/blob/62e032f89e5ddc3c504f47013c31a9838715afd5/test/Arbitrary/Repline.hs#L7
The rumor is, it's unsafe. But it works to get nested Coercable applicative monoids. Here's the scoop: I want to randomly select an element out of a container. If the container is foldable this can be done using
foldMap
and monoids:This is done by mapping each element (
x
) in the structure and to QuickCheck'sGen
applicative that selects eitherNothing
orJust x
. TheAp
andFirst
are newtype wrappers to make sure that one theFirst
Just
value is extracted and because we're folding andGen
isn't a monoid in its own right we have to piggy pack onAp
which is a monoid wrapper around applicatives.As you can see
pickOne
is really the heart of this function but it's surrounded by a bunch of wrapping and unwrapping code to handle the newtypes. However,Newtype
from thenewtype
package was built just for this. However, there's a slight problem.Ap f a
unwraps tof a
. This isn't an issue if we don't want to unwrapa
. But, in our case,a ~ First b
needs to unwrap toMaybe b
. So we need aNewtype
instance (the functor constraint to to ensure we can go up under thef
and unwrap thea
):which the library doesn't provide. So I had to write my own:
This requires
UndecidableInstances
extension. I'm not sure why but the compiler told me so and it's the boss...But! Using this I can coerce my heart's content to wrap and unwrap newtypes. As I think about it I wonder how useful lenses would have been here...