Code Monkey home page Code Monkey logo

Comments (9)

emmanueltouzery avatar emmanueltouzery commented on August 27, 2024

Hi! Yes, I believe these are applicatives.

so if I look for instance at your crocks link:

// add :: Number -> Number -> Number
const add =
  x => y => x + y

Maybe.of(add)
  .ap(Just(5))
  .ap(Just(27))
//=> Just 32

It seemed to me that the 'lift' approach is easier to handle with typescript (but this can be discussed). So one way to express this same thing in prelude today is like that:

const lifted = Option.liftA2((x:number,y:number) => x+y);
lifted(Option.of(5), Option.of(6));
=> Option.of(11)

const lifted2 = Option.liftA2((x:number,y:number) => x+y);
lifted2(Option.of(5), Option.none<number>());
=> Option.none()

For that specific use-case we achieve the same outcome.

liftA2 is obviously limited to only two parameters. For more, there is liftAp.

const lifted = Option.liftAp((x:{a:number,b:number,c:number}) => x.a+x.b+x.c);
lifted({a:Option.of(5), b:Option.of(6), c:Option.of(3)});
=> Option.of(14)

The lift functions are also available for other functors, like Either and so on.

As per your research, it seems that the ap approach is really seeing more adoption. I'm not sure whether the difference is only ergonomics or whether it also has other advantages. I think at the time I picked the lift approach also because I thought the ap type signature could be messy. This could be revisited potentially.

from prelude-ts.

jderochervlk avatar jderochervlk commented on August 27, 2024

I'm not an expert on ADTs, but I am used to seeing things like ap and chain, which seem to be similar to lift but not quite the same.

I found this from some googling:

When "lift" is referred to as a function, though, it's just a variation of map, ap, or chain that takes the function argument first, and returns a new function that takes the functor value and maps/aps/chains on it. That is, given the map-equivalent version of lift, arg.map(f) is identical to lift(f)(arg). Lifting the function, rather than using map directly, makes it easier to pass the function around and apply it to other values, as it lets you use normal function-call syntax, passing arguments, rather than having to specially use the map method.

I'll keep doing some more digging and see if I can do what I want with lift, but it might be good to include alternate ways of doing things, or at least documenting the differences.

from prelude-ts.

jderochervlk avatar jderochervlk commented on August 27, 2024

I think I was able to wrap my head around how to use lift to replace ap, but it has brought something else to my attention.

Consider this workflow (using crocks):

import Maybe from 'crocks/Maybe'

// define two people, one with a defined age and one without
const personOne = Maybe.of({
    name: 'Bob',
})
const personTwo = Maybe.of({
    name: 'Jane',
    age: '33'
})

// this function returns Just the age or Nothing
const getAge = x => 
    x.age ? Maybe.Just(x.age) : Maybe.Nothing()

// get the age and log it, or log that age is not defined
const logAge = x => 
    x.chain(getAge)
     .coalesce(
        () => console.log('age is not defined'),
        console.log
        )

logAge(personOne)
// age is not defined

logAge(personTwo)
// 33

This is a pretty common pattern for me (I use it for rendering a react component if data exists, or rendering an empty state).

Without chain or coalesce I am not sure how to go about creating this flow using prelude-ts.

Perhaps this is a different way of thinking that doesn't line up with prelude-ts.

Since I am expanding the scope of my issue, should I rename or change this issue into something else?

from prelude-ts.

emmanueltouzery avatar emmanueltouzery commented on August 27, 2024

I think instead of chain you want prelude's flatMap and instead of coalesce you want.. well if you want to return something, you'd use getOrElse or getOrCall. If you just want the side-effect in case the option is not present you'd use ifNone.

The concepts are mostly the same, it's just one style or the other I think.

from prelude-ts.

jderochervlk avatar jderochervlk commented on August 27, 2024

Ah, that makes sense.

Here is what I've come up with:

import { Option } from 'prelude-ts'

const { log } = console

const personOne = Option.of({
    name: 'Bob',
})
const personTwo = Option.of({
    name: 'Jane',
    age: '33'
})

const getAge = (x: { age?: number }) => 
    x.age ? Option.some(x.age) : Option.none()

const logAge = (x: Option<any>) => 
    x.flatMap(getAge)
    .ifNone(() => console.log('age is not defined'))
    .map(log)


logAge(personOne)
// age is not defined

logAge(personTwo)
// 33

Is there a language or source for the inspiration of prelude-ts that could help me understand?

from prelude-ts.

emmanueltouzery avatar emmanueltouzery commented on August 27, 2024

Prelude-ts is inspired by the vavr Java library, itself inspired by the Scala language.

Did you see the prelude user guide?

from prelude-ts.

jderochervlk avatar jderochervlk commented on August 27, 2024

I did take a look through that guide. I can try and wrap my head around Scala better, but I'm not sure I'd be able to sell prelude-ts to a team with the current documentation.

I would love to be able to use something like prelude-ts (adts in TypeScript), but I wish it had the level of documentation of ramda or crocks to make it a bit more accessible to people not familiar with Scala.

I'll keep an eye on this library and keep playing around with it, but I am not sure it meets my needs at this point.

from prelude-ts.

emmanueltouzery avatar emmanueltouzery commented on August 27, 2024

No problem! I think it's a matter of which library gives you what you need. What prelude does better than the others, it seems to me, would be on the collections side, especially the proper hashmap with hashing & equality, enabling a proper groupBy for instance, and typescript types (but fp-ts may be even better on that, not sure).

Certainly I would keep this bug open, regarding the ap feature, that's a good point. I'll try to find some time at some point in the future to think how to implement this in a way that the types work out. It may not be possible though.

In the end, I think the differences here are really more cosmetic, these are all functors, applicatives, monads. So i'm really happy to see that ecosystem of solutions!

from prelude-ts.

jderochervlk avatar jderochervlk commented on August 27, 2024

I agree about the collections! That is one of the really appealing things to me.

from prelude-ts.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.