I'm still digesting the changes in ap, and reading again the discussions in #50 and #144, and there's a thing that bothers me.
With the current specifications we have to access the value contained in another Apply directly and that feels very wrong (example here).
What about having all "container" types override the inherited Object.prototype.valueOf to get the contained value?
Should be useful in more cases, and for more reasons, than the ap one I'm mentioning now.
With the current specifications we have to access the value contained in another
Applydirectly and that feels very wrong
What makes it feel wrong to you?
The author of a data type knows how to access its private fields. Accessing the private value field of b is no different from accessing the private value field of this in new Id(b.value(this.value)).
:thumbsdown: for doing anything with valueOf. It isn't necessary, and the thought of specifying a method primarily used for type coercion is concerning. Furthermore it would be tragic to see people use Maybe#valueOf rather than safely unwrap a value with a function such as fromMaybe.
To echo what @davidchambers said - ValueOf magic feels really hacky and would build more confusion to something that already people are trying to grasp initially.
What makes it feel wrong to you?
That I'm accessing a "private" member of a parameter supplied by the caller: it's quite different from accessing a private member of my own implementation.
Even if the received parameter is supposed to be of the same type, fantasy-land should be about interoperability before anything else.
If I have some fl compatible library returning, for example, an Option I should be able to use it with, say, Sanctuary's Maybe as maybe Sanctuary is my preferred choice.
I don't see anything concerning about using valueOf as I proposed, nor I see anything "magic" in it.
valueOf seems suitable to me, but the point stands even for any "unwrap" function.
Furthermore it would be tragic to see people use
Maybe#valueOfrather than safely unwrap a value with a function such asfromMaybe
As "tragic" as accessing its value property, isn't it?
Anyway was just an idea: thanks for your thoughts.
If I have some fl compatible library returning, for example, an Option I should be able to use it with, say, Sanctuary's Maybe as maybe Sanctuary is my preferred choice.
This is why i've reiterated many many times to stop building your own Maybe, Option types. Sure they're easy to do, but they're not always correct and they don't always conform to the specification esp. around null or undefined. We should instead build one type and work with that, then use iterations to enhance it. Forking a type will inevitably lead to inconsistencies. (I don't mind which one we use, fantasy-land, sanctuary, ramda - I wonder if we should promote ones over another, anyway!).
If you can prove that valueOf can have laws around it and that it's consistent for every time you call it then yes we can use it, but I know for a fact you can't because it's used for other things so it leads to bad scenarios and then the method becomes magic as you don't know what it does in those circumstances.
Furthermore it would be tragic to see people use
Maybe#valueOfrather than safely unwrap a value with a function such asfromMaybeAs "tragic" as accessing its
valueproperty, isn't it?
Users should not access the private value property of a Just, but the data type's implementation is free to do so.
Perhaps you're asking what the harm is in specifying valueOf if users can already shoot themselves in the feet by referencing value? The difference is that private properties of a data type are undocumented, whereas specifying valueOf would encourage library authors to document the method's behaviour, which in turn would encourage users to write expressions such as…
> Just(2) + Just(2)
4
and…
> Just(2) + Nothing
NaN
which would lead to sadness. I also have no idea what the result of Left(2) + Right(2) should be.
Even if the received parameter is supposed to be of the same type, fantasy-land should be about interoperability before anything else.
On this I completely agree. :thumbsup:
If I have some fl compatible library returning, for example, an
OptionI should be able to use it with, say, Sanctuary'sMaybeas maybe Sanctuary is my preferred choice.
This is an admiral goal, and your proposal would make this possible.
Another option is to define a natural transformation from one data type to the other. For example:
const RF = require('ramda-fantasy');
const S = require('sanctuary');
// eitherToEither :: SanctuaryEither a b -> RamdaFantasyEither a b
const eitherToEither = S.either(RF.Either.Left, RF.Either.Right);
This is certainly not ideal. Thank you, @ascartabelli, for explaining your motivation. I agree that true interoperability would not require natural transformations such as the one above. I'm just not sure whether this sort of interoperability is possible without specifying the data types themselves (Maybe, Either, etc.).
This is why i've reiterated many many times to stop building your own Maybe, Option types.
ramda/ramda-fantasy#139
This is why i've reiterated many many times to stop building your own Maybe, Option types.
Well, there's a difference in proposing a specification and proposing to adopt a standard library.
If you can prove that valueOf can have laws around it and that it's consistent for every time you call it then yes we can use it, but I know for a fact you can't
I can't, obviously: a wacky implementation will always be a wacky implementation.
An unintended behavior I haven't considered is what @davidchambers mentioned about having:
Just(2) + Just(2) // => 4
Although one can argue that currently, using Sanctuary for example, you get:
Maybe(2) + Maybe(2) // => "Maybe.Just(2)Maybe.Just(2)"
Which could be considered odd in the same way.
But seriously, yes, although I don't think it would encourage people in writing such things, @davidchambers makes a good point: there's probably no need in adding more unexpected behavior.
My point about interoperability, as I previously said, still stands though as another function could be used for the same purpose.
:+1:
On Tue, 29 Nov 2016, 13:12 Andrea Scartabelli, notifications@github.com
wrote:
This is why i've reiterated many many times to stop building your own
Maybe, Option types.Well, there's a difference in proposing a specification and proposing to
adopt a standard library.If you can prove that valueOf can have laws around it and that it's
consistent for every time you call it then yes we can use it, but I know
for a fact you can'tI can't, obviously: a wacky implementation will always be a wacky
implementation.An unintended behavior I haven't considered is what @davidchambers
https://github.com/davidchambers mentioned about having:Just(2) + Just(2) // => 4
Although one can argue that currently, using Sanctuary for example, you
get:Maybe(2) + Maybe(2) // => "Maybe.Just(2)Maybe.Just(2)"
Which could be considered odd in the same way.
But seriously, yes, although I don't think it would encourage people in
writing such things, @davidchambers https://github.com/davidchambers
makes a good point: there's probably no need in adding more unexpected
behavior.My point about interoperability, as I previously said, still stands though
as another function could be used for the same purpose.—
You are receiving this because you commented.Reply to this email directly, view it on GitHub
https://github.com/fantasyland/fantasy-land/issues/205#issuecomment-263566245,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACcaGOX5uMSe6ZgTtI6qSv49TgVWfufiks5rDCSdgaJpZM4K-3Rm
.
in some cases you have multiple values (or no value) in one object:
List a = Nil | Cons a (List a) -- 2 value
Tree a = Leaf | Node (Tree a) a (Tree a) -- 3 value
if you have some type T and method ap it's type is
ap :: T a ~> T (a -> b) -> T b
Class T<A> {
public T<B> ap(T<Function1<A,B>) { ... }
}
you should not pass objects of different type then it needs objects of the same type T. if you want to work with different type of values you should convert them to the T before you call the ap.
As "tragic" as accessing its value property, isn't it?
this is not tragic even in classical OOP languages, you can access your own private fields in the same class.
// PHP example. runnable version http://ideone.com/vCLncT
class Obj{
private $value;
function __construct($num) {
$this->value = $num;
}
function add($other) {
return new Obj($this->value + $other->value);
}
function show() {
echo $this->value;
}
}
$a = new Obj(1);
$b = new Obj(2);
$a->add($b)->show(); // 3
// Java example. runnable version http://ideone.com/3fK8my
class Obj
{
private int value;
public Obj(int v) {
value = v;
}
public Obj add(Obj other) {
return new Obj(value + other.value);
}
public void show() {
System.out.println(value);
}
}
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
Obj a = new Obj(1);
Obj b = new Obj(2);
a.add(b).show(); //3
}
}
My point about interoperability, as I previously said, still stands though as another function could be used for the same purpose.
@ascartabelli to "extract" contained value you can define extract method from Comonad, but not every type is comonad and not every instance of type holds value (List.Nil, Tree.Leaf).
Basically we already have a method for extracting value from container, so i think this should be closed if there are no more things to discuss.
to "extract" contained value you can define extract method from Comonad, but not every type is comonad and not every instance of type holds value (List.Nil, Tree.Leaf).
Basically we already have a method for extracting value from container, so i think this should be closed if there are no more things to discuss.
@safareli, yes I get your point, but that's why I proposed the use of valueOf in the first place: it's already there for every JavaScript object and has the default behaviour of returning the object itself if it isn't overridden.
I also understand @davidchambers and @SimonRichardson and their efforts about trying to reduce fragmentation of common types, but my "proposal" (was actually meant more as food for thought) stems from another fragmentation problem.
In the JavaScript world nowadays I see a real problem of dependency hell, and not only because of that madness of npm modules containing only one basic function.
Going back to example about interoperability I made above: I think it's legit if a developer decides to implement his own simple Maybe in his fantasy-land compatible library and have some of his functions return it.
There's some fragmentation, yes, but as @SimonRichardson says even with very basic types you may face problems:
This is why i've reiterated many many times to stop building your own Maybe, Option types. Sure they're easy to do, but they're not always correct and they don't always conform to the specification
If a common algebra doesn't make you safe, I think it's practical to adapt to the language you're using and consider extending the specifications a bit further than a set of mathematics laws.
That is, because we're talking about specifications to favor interoperability, not trying to promote a standard library.
Most helpful comment
What makes it feel wrong to you?
The author of a data type knows how to access its private fields. Accessing the private
valuefield ofbis no different from accessing the privatevaluefield ofthisinnew Id(b.value(this.value)).:thumbsdown: for doing anything with
valueOf. It isn't necessary, and the thought of specifying a method primarily used for type coercion is concerning. Furthermore it would be tragic to see people useMaybe#valueOfrather than safely unwrap a value with a function such asfromMaybe.