Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

everything #1

Open
wants to merge 40 commits into
base: main
Choose a base branch
from
Open

everything #1

wants to merge 40 commits into from

Conversation

davidchambers
Copy link
Member

Once this is published we'll be able to define S.lens, S.view, S.over, and S.set. :)

I won't describe Constant a b here as the documentation should explain its use (although not necessarily its purpose). If you believe the documentation is lacking in any way, please say so.

test/index.js Outdated
('Constant (Constant (Constant (Number)))' +
' (Constant (Constant (Number))' +
' (Constant (Number)' +
' (-0)))');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂

index.js Outdated
//. ```
(function() {
var empty;
try { empty = Z.empty (A); } catch (err) { return; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kinds of errors can happen here? Could the attachment of ['fantasy-land/of'] be done in the Constant$bound function with something like Z.Monoid.test?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I guess it can't be done in Constant$bound itself, since you need it before you have a value, but couldn't it nevertheless use Z.Monoid.test(A)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Z.Monoid.test takes a value rather than a type representative:

> Z.Monoid.test ('abc')
true

> Z.Monoid.test (String)
false

What kinds of errors can happen here?

> Z.empty (Number)
TypeError: Monoid.methods.empty(...) is not a function

I would like to avoid try...catch, but I can't see how to do so.

Copy link
Member

@masaeedu masaeedu Mar 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's off topic here, but do you think it would be a good idea to add an equivalent that does work on the type rep? Then if you have some function that can take a value and obtain it's type rep, and a function that can take a type rep and determine whether it implements a typeclass, their composition is test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would for example allow you to avoid using the try/catch here; all the class membership testing can be done on the A typerep outside of the Constant$bound constructor, and then in Constant$bound you just need to test whether the typerep of value is indeed A.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea! I'll investigate changes to sanctuary-type-classes which would enable this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure, but this approach might also yield some minor performance improvements elsewhere, by moving some checking out of the path where values are being moved around.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has an issue been posted in sanctuary-type-classes to keep track of this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then if you have some function that can take a value and obtain [its] type rep, and a function that can take a type rep and determine whether it implements a typeclass, their composition is test.

fantasyland/fantasy-land#315 is the ultimate solution to this problem, I believe. Implementing that proposal is near the top of my list of Sanctuary-related tasks. :)

Comment on lines +12 to +14
//. A value of type `Constant a b` always contains exactly one value,
//. of type `a`. Mapping over a `Constant a b` has no effect because
//. the `b -> c` function is never applied.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand the Constant type, why it takes a type representative, and how that type representative relates to Constant's the type parameters. If you care to explain it to me, maybe that explanation can be added here to the introduction. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Haskell, we can do this:

> import Data.Functor.Constant

> pure 42 :: Constant String Int
Constant ""

We provided 42 :: Int in “b” position; "" :: String materialized in “a” position.

In JavaScript, keeping track of a and b in the type system is not an option so we must provide type information explicitly:

> S.of (Constant (String)) (42)
Constant (String) ('')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"" :: String materialized

Woah. o.o .... Ahh, because String is a Monoid. So Constant (Boolean) will throw when instantiated.

Alright. That makes things clearer. I don't really see how this would be used in practice, and that's probably what most of my confusion stems from.

index.js Outdated
Comment on lines 98 to 102
//# Constant :: TypeRep a -> a -> Constant a b
//.
//. Constant's sole data constructor. The [type representative][] makes
//. `Constant (M)` an [Applicative][]-compatible type representative if
//. `M` represents some monoidal type.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this helpful, @Avaq?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read this a few times yesterday, but without being able to think up a practical use-case, I couldn't understand what it's for.

Copy link
Member

@masaeedu masaeedu Jan 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Avaq Imagine you're trying to derive:

foldMap :: Monoid m -> (a -> m) -> f a -> m

from:

traverse :: Applicative g -> (a -> g b) -> f a -> g (f b)

So you start writing:

const foldMap = ({ empty, append }) => am => fa => {
  // ?
}

Now obviously the only tool you have available is traverse, from which you're trying to derive foldMap, so you write:

const foldMap = ({ empty, append }) => am => fa => traverse(/* ?1 */)(/* ?2 */)(/* ?3 */)

Now you're stuck with the task of producing an Applicative g to feed into ?1, an a -> g b to feed into ?2 and a f a to feed into ?3. It just so happens we already have an fa :: f a we received from the arguments, so that takes care of ?3 at least:

const foldMap = ({ empty, append }) => am => fa => traverse(/* ?1 */)(/* ?2 */)(fa)

Let's think about the types again:

traverse :: Applicative g -> (a -> g b) -> f a -> g (f b)
foldMap  :: Monoid m      -> (a -> m)   -> f a -> m

we can see a few things:

  • it must be the case that g (f b) = m
  • g (whatever it is) needs to have an instance Applicative g
  • this derivation must work regardless of what traversable f is: i.e. f b could be any type whatsoever
  • m again is beyond our control: so whatever (a -> m) the user provides to foldMap, it is precisely for that m that we must have g (f b) = m

So, what's an applicative functor g such that g x = m for an arbitrary type x and an arbitrary monoid m? 😉

index.js Outdated
Comment on lines 150 to 151
// XXX: sanctuary-show@3 only respects @@show on "objects". Fool it.
Constant$bound[Symbol.toStringTag] = 'Object';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Avaq, here's a workaround for the issue we discussed not so long ago.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this become a standard way of working? It seems a bit hacky.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants