everything#1
Conversation
| ('Constant (Constant (Constant (Number)))' + | ||
| ' (Constant (Constant (Number))' + | ||
| ' (Constant (Number)' + | ||
| ' (-0)))'); |
| //. ``` | ||
| (function() { | ||
| var empty; | ||
| try { empty = Z.empty (A); } catch (err) { return; } |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
Z.Monoid.test takes a value rather than a type representative:
> Z.Monoid.test ('abc')
true
> Z.Monoid.test (String)
falseWhat kinds of errors can happen here?
> Z.empty (Number)
TypeError: Monoid.methods.empty(...) is not a functionI would like to avoid try...catch, but I can't see how to do so.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Great idea! I'll investigate changes to sanctuary-type-classes which would enable this.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Has an issue been posted in sanctuary-type-classes to keep track of this?
There was a problem hiding this comment.
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. :)
| //. 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. |
There was a problem hiding this comment.
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. :)
There was a problem hiding this comment.
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) ('')There was a problem hiding this comment.
"" :: Stringmaterialized
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.
| //# 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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
@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 instanceApplicative g- this derivation must work regardless of what traversable
fis: i.e.f bcould be any type whatsoever magain is beyond our control: so whatever(a -> m)the user provides tofoldMap, it is precisely for thatmthat we must haveg (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? 😉
e3ab0c4 to
9221f73
Compare
| // XXX: sanctuary-show@3 only respects @@show on "objects". Fool it. | ||
| Constant$bound[Symbol.toStringTag] = 'Object'; |
There was a problem hiding this comment.
@Avaq, here's a workaround for the issue we discussed not so long ago.
There was a problem hiding this comment.
Would this become a standard way of working? It seems a bit hacky.
There was a problem hiding this comment.
Once this is published we'll be able to define
S.lens,S.view,S.over, andS.set. :)I won't describe
Constant a bhere 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.