Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Apr 12 14:00
    beck commented #177
  • Sep 29 2020 16:09
    davidchambers commented #286
  • Sep 29 2020 15:40
    Raiondesu commented #286
  • Sep 29 2020 15:05
    Raiondesu commented #177
  • Sep 22 2020 16:46
    juboba commented #325
  • Sep 22 2020 13:35
    CrossEye commented #325
  • Sep 18 2020 20:49
    juboba commented #325
  • Sep 07 2020 16:14
    richytong commented #302
  • Aug 30 2020 17:41
    rpominov review_request_removed #281
  • Jul 11 2020 08:45
    ivenmarquardt closed #320
  • Jul 11 2020 08:45
    ivenmarquardt commented #320
  • Jul 02 2020 16:47
    alexr007 commented #325
  • Jul 02 2020 16:46
    alexr007 commented #325
  • Jul 02 2020 16:05
    CrossEye commented #325
  • Jul 02 2020 06:15
    davidchambers commented #325
  • Jul 02 2020 06:14
    davidchambers commented #325
  • Jul 02 2020 03:50
    Munkyu-Yang opened #325
  • Jun 20 2020 16:58

    davidchambers on master

    Add purify to list of implement… Merge pull request #324 from gi… (compare)

  • Jun 20 2020 16:58
    davidchambers closed #324
  • Jun 20 2020 16:58
    davidchambers commented #324
David Chambers
@davidchambers
Interesting question, @juboba!
Ludwig Magnusson
@TheLudd
image.png
Hello.
Can Const be a functor?
It seems that it will follow the specifications in 1 and 2, but not the description of the map method here:
Example:
// string -> number
const strlen = (str) => str.length

class Const {
  construtor(v) {
    this.v = v;
  }

  ['fantasy-land/map'](f) {
    return this;
  }
}

// Const[string]
const a = new Const('hello')

// Const[string] (should be Const[number] according to FL spec)
const b = a['fantasy-land/map'](strlen)
David Chambers
@davidchambers
Here's how it works in Haskell, @TheLudd:
> import Data.Functor.Const (Const(..))

> fmap length (Const False)
Const False
We can see that the type of Const False is context-dependent:
> :type Const False
Const False :: Const Bool b

> :type fmap length (Const False)
fmap length (Const False) :: Const Bool Int
fmap length (Const False) transforms Const Bool String into Const Bool Int, just as fmap length Nothing transforms Maybe String into Maybe Int.
Ludwig Magnusson
@TheLudd
Don't really understand here.... What does Const Bool Int and Const Bool Stringmean?
David Chambers
@davidchambers
Are you aware that Const is a binary type constructor?
> :kind Const
Const :: * -> k -> *

> :kind Const Bool
Const Bool :: k -> *

> :kind Const Bool String
Const Bool String :: *
Ludwig Magnusson
@TheLudd
No I was not. Is it the same for Const used intrnally in ramda?
David Chambers
@davidchambers
I believe so.
Ludwig Magnusson
@TheLudd
Is this not unary?
// `Const` is a functor that effectively ignores the function given to `map`.
var Const = function(x) {
  return {value: x, 'fantasy-land/map': function() { return this; }};
};
David Chambers
@davidchambers
That's the data constructor, which is unary.
> :type Const
Const :: a -> Const a b
Aldwin Vlasblom
@avaq:matrix.org
[m]
Just like Either being a binary type (Either a b), but its data constructors both being unary Left :: a -> Either a b, Right :: b -> Either a b. The Const type only has one data constructor, and it's a little confusing that it has the same name as its type.
Ludwig Magnusson
@TheLudd
It is the data constructor but it is also, as far as I can tell, the entire implementation of Const in ramda. And I cannot see the binary type there.
David Chambers
@davidchambers
There are no types in JavaScript. ;)
The types exist only in our minds.
Aldwin Vlasblom
@Avaq

@TheLudd You can think of the second type in Const a b as never obtaining a concrete value. Let me give you an example using Fluture:

//    myFuture :: Future a String
const myFuture = F.after (Infinity) ('hello from past the end')

//    myNewFuture :: Future a Number
const myNewFuture = F.map (message => message.length) (myFuture)

In the above example, I changed the type of the Future from Future a String to Future a Number even though the value inside the Future never actually materializes at runtime. The same is true for Const a b. When constructing a Const, one provides the a, and the b never actually materializes. But since b is the subject of the Functor instance, it is possible to think of it as having a type.

Oh, and to combat an ambiguity there: Nothing in my example explicitly relies on the usage of after (Infinity). I might have just as well constructed the Future like: Future (() => () => {}) (a Future that never calls its continuations with anything), and also thought of it as having type Future a String.
Aldwin Vlasblom
@Avaq
Hmm.. Maybe this would be a good way to say it: Const is like Either, if the only constructor you had was Left. :P
Is that really true, anyone? :o
David Chambers
@davidchambers
That sounds right to me, Aldwin.
Álvaro Touzón
@kasselTrankos
too @Avaq , the one thing that move me to use is to take semantic
Ludwig Magnusson
@TheLudd
@Avaq Ok. let me ask then. Can Const be a Comonad? Can the value be extracted?
Because that would create this situation which seems not correct:
extract(map(length, Identity['fantasy-land/of']('hello'))) // => 5
extract(map(length, Const['fantasy-land/of']('hello'))) // => 'hello'
David Chambers
@davidchambers
In a Const a b value there is no b to extract, so Const a b cannot satisfy the requirements of Comonad.
Ludwig Magnusson
@TheLudd

So.... this might be my final question in this subject then....
What is the internal Const in ramda?
Because while it does not have an extract method, other functions are picking the public valueproperty, which in my mind is basically the same as extract.
Is this law-breaking cheating to get lenses to work or is the behavior lawful?

// from source/view.js
var Const = function(x) {
  return {value: x, 'fantasy-land/map': function() { return this; }};
};
....
var view = _curry2(function view(lens, x) {
  return lens(Const)(x).value;
});

This can be compared to the use of Identity which is capable of implementing extract

// from source/over.js
var Identity = function(x) {
  return {value: x, map: function(f) { return Identity(f(x)); }};
};
...
var over = _curry3(function over(lens, f, x) {
  return lens(function(y) { return Identity(f(y)); })(x).value;
});
David Chambers
@davidchambers

Is this law-breaking cheating to get lenses to work or is the behavior lawful?

Fantasy Land does not restrict the properties a value may provide. For example, S.Pair ('abc') (123) has fst and snd properties which have nothing to do with the Fantasy Land specification. Similarly, Ramda's Const (42) has a value property. This is not cheating. The value property is neither lawful nor unlawful as it is unrelated to the Fantasy Land laws.

Jakub Barczyk
@jakubbarczyk
@davidchambers would you say that Fantasy Land spec outlines "behavior" -- what extra fields we put in our implementation, as long as they serve the behavior, it's all good?
David Chambers
@davidchambers
That sounds right to me, @jakubbarczyk.
Ludwig Magnusson
@TheLudd
@davidchambers but when you create those types like Pair, do you intend them to be used by accessing the properties directly and not only through the FL api?
David Chambers
@davidchambers
That's right.
Ludwig Magnusson
@TheLudd

ok sounds counter-intuitive to me.
Like if I have a Maybe:

const m = getMaybe()
if (m.value) {
  // handle Just
} else {
  // handle Nothing
}

would you do something like this as well?

David Chambers
@davidchambers
Certainly not.
I would use a function such as this:
maybe :: b -> (a -> b) -> Maybe a -> b
Ludwig Magnusson
@TheLudd
that's my point.
So isn't these other cases really the same? If you'd want a value that is wrapped in an Identity you'd use extract right?
David Chambers
@davidchambers
Sure, but Fantasy Land does not define every useful operation a type could support. Perhaps the maybe function above could be implemented using fantasy-land/* methods exclusively, but this should not be a requirement.
What is it that concerns you about S.Pair ('abc') (123) having fst and snd properties?
Ludwig Magnusson
@TheLudd
I haven't used Pairso nothing really. Just when I create types I never expect the inner things to be used externally.
Also, making a type follow the laws of FL means that you can make assumptions about your types. But if you go around it by accessing inner properties of those types in your code you might lose that ability it seems.
David Chambers
@davidchambers
I understand your nervousness. In the case of Ramda's Const implementation, the user never even sees the object with the value property. ;)
Ludwig Magnusson
@TheLudd
I am not nervous, just trying to understand the Const type through the example of Ramda
Ludwig Magnusson
@TheLudd
However...
Does this mean that Const can be foldable. And in that case it would work like Left and Nothing, i.e. just returning the initial value?
var Const = function(x) {
  return {
    value: x,
    'fantasy-land/map': function() { return this; },
    'fantasy-land/reduce': function(f, init) { return init; }
  };
};
David Chambers
@davidchambers
That looks correct to me.
Aldwin Vlasblom
@avaq:matrix.org
[m]
Isn't Const just Left in every way, with the one exception that there is no Right for Const as there is for Left? And if so, couldn't Const implement all the same Fantasy methods implementable by Either, in exactly the way they are implemented on Left? https://github.com/sanctuary-js/sanctuary-either
David Chambers
@davidchambers
I think so, Aldwin. :)
Ludwig Magnusson
@TheLudd
Const, Left and Nothingthen I assume
David Chambers
@davidchambers

Aldwin is suggesting that these are equivalent:

data Const a b = Const a
data Either a b = Left a

Names don't matter. :)

Aldwin Vlasblom
@avaq:matrix.org
[m]
@TheLudd: Not Nothing, because Nothing doesn't carry an inner value. Const and Left do.