Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jan 30 10:17
  • Jan 22 13:29
    cdoublev commented #215
  • Jan 21 23:57

    robotlolita on v4.x

    (compare)

  • Jan 21 23:56

    robotlolita on 2.1.0

    (compare)

  • Jan 21 23:56

    robotlolita on deferred-message

    (compare)

  • Jan 21 23:56

    robotlolita on union-constructors

    (compare)

  • Jan 21 23:55
    robotlolita closed #186
  • Jan 21 23:55
    robotlolita closed #185
  • Jan 21 23:55
    robotlolita closed #184
  • Jan 21 23:55
    robotlolita closed #183
  • Jan 21 23:55
    robotlolita closed #182
  • Jan 21 23:55
    robotlolita closed #181
  • Jan 21 23:55

    robotlolita on typescript

    (compare)

  • Jan 21 23:54

    robotlolita on gh-pages

    (compare)

  • Jan 21 23:54

    robotlolita on logo

    (compare)

  • Jan 21 23:25
    robotlolita commented #215
  • Jan 21 23:24
    robotlolita labeled #215
  • Jan 21 23:19

    robotlolita on v2.3.2

    (compare)

  • Jan 21 23:16

    robotlolita on master

    Updates changelog, version to 2… More stylistic fixes (compare)

  • Jan 21 15:42
Quil
@robotlolita
Yeah, the contract part is a lot like clojure.spec (with optional static checking). There are other aspects that are harder to tack on top of JS, like object-capability security
Mike Lambert
@lax4mike
hi @robotlolita ! I'm making map tiles and running a Task on about 5,000 images. I'm trying to do it in parallel by reduceing over the list of Tasks and connecting them with .and. I'm running into an issue with the max call stack being exceeded, but I think it's just because I have so many images... do you have an advice?
    function makeInstance() {
                         ^

RangeError: Maximum call stack size exceeded
    at makeInstance (/www/nz-topo/node_modules/folktale/adt/union/union.js:86:26)
    at new Deferred (/www/nz-topo/node_modules/folktale/concurrency/future/_deferred.js:83:26)
    at Task.run (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:404:22)
    at Task._computation (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:341:36)
    at Task.run (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:445:28)
    at Task._computation (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:341:36)
    at Task.run (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:445:28)
    at Task._computation (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:341:36)
    at Task.run (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:445:28)
    at Task._computation (/www/nz-topo/node_modules/folktale/concurrency/task/_task.js:341:36)
Mike Lambert
@lax4mike
I ended up generating images for 1 zoom level less, which brought the number of images down from 5k to 1.5k
Mike Lambert
@lax4mike
so, i actually fixed in a much better way. a while back, @robotlolita helped me make a helper to process an array of Tasks sequentially :
// given an array of something and a transform function that takes an item from
// the array and turns it into a task, run all the tasks in sequence.
// inSequence :: (a -> Task) -> Array<a> -> Task
export const inSequence = R.curry((transform, items) => {
  let log = [];

  return items.reduce((pipe, item, i) => {
    // build up a chain of tasks
    return (
      pipe
        // transform this item to a task
        .chain(() => transform(item))
        // after it's done, push the result to and return the log
        .map(result => {
          log.push(result);
          return log;
        })
    );
  }, Task.of("start"));
});
using that same pattern, I created a helper to join tasks with .and:
// given an array of something and a transform function that takes an item from
// the array and turns it into a task, run all the tasks concurrently.
// concurrently :: (a -> Task) -> Array<a> -> Task
export const concurrently = R.curry((transform, items) => {
  return items.reduce((pipe, item, i) => {
    return (
      pipe
        // transform this item to a task
        .and(transform(item))
    );
  }, Task.of("start"));
});
using those two, I created another to process the tiles in chunks:
// given an array of something and a transform funcion that takes an item from
// the array and turns it into a task, run all the tasks in chunks.
// Sometimes, using inSequence or concurrently can go over the max call stack.
// Processing those in chunks solves that error.
// inChunks :: (a -> Task) -> Array<a> -> Task
export const inChunks = R.curry((transform, items) => {
  const chunks = R.splitEvery(1000, items);

  return inSequence(chunk => {
    return concurrently(transform, chunk);
  }, chunks);
});
using this allows me to process a lot of tiles (~5k) without blowing the max call stack
// files is an array of length ~5k
.chain(files => {
  return inChunks(file => {
    return copyOrMergeTile(file).map(() => file);
  }, files);
})
Quil
@robotlolita

@lax4mike ah, yeah, sadly Task isn't stack safe, so long (synchronous) sequences will blow up the stack. Currently the only way to avoid this is by inserting some asynchronous process in the middle of the long sequence of synchronous ones to clean up the stack.

Generalised effects (https://github.com/robotlolita/effects) will be stack safe, but they might only be added to folktale by the end of this year. I'd like TypeScript to have a way of typing them (even if an unsound one, since soundness would require linear types).

Generalised effects will allow writing direct-style functions like this (https://github.com/robotlolita/effects/blob/master/examples/simple/guess.js#L8-L29) in a more composable, pure, and testable way than the monadic tasks currently provide.
Jesse Warden
@JesterXL
Yo @robotlolita come on dude, you've started Purr like 3 times now, we're all so damn excited, can you show like an example function + module? I looked for examples in the repo, I swear. Please please please!
Also, you still thinking just contracts or that + types or...?
Also, this still just for Node type stuff or browser too?

newtoys

Jesse Warden
@JesterXL
BTW, I've found union types great for making Redux easier to model async state. Blog post: http://jessewarden.com/2019/02/easier-asynchronous-state-modelling-in-react-redux-or-hooks.html
Matheus Ashton Silva
@ashton

Hello! My name is Matheus, I'm a brazilian developer and a functional JS enthusiast. I'm new here, so, excuse me if I do something wrong.

I use folktalke implementations at work, and I want to thank you very much for that!

Recently I've seen a deprecation warning regarding nullableToResult telling me that I should pass a second argument, being a default value to it.

I had a question so decided to ask it here
since we have getOrElse on Result.Error, being a "safe" way of accessing the value inside of it
and the default value of getOrElse overrides the default value passed to nullableToResult
I got confused about the best way of handling this, and how it was meant to be used
Can you help me?
Sorry if it is a dumb question
Jesse Warden
@JesterXL
I don't have context as to why you're getting a deprecation, but I know rest parameters like (...stuff) are hard to handle in curried / partial application situations, so purists prefer that you clearly state all arguments vs. providing defaults. Also, we don't have a good "nothing" like other languages like Python. In JavaScript we have undefined and null and sometimes ''. I would stick to getOrElse, otherwise, you can use matchWith to use a function to make it based on if it's an Ok or an Error.
Matheus Ashton Silva
@ashton
When I referred to default value I meant the data that will be assigned to Result.Error if the value passed to nullableToResult is null, or undefined, like here in the docs: https://folktale.origamitower.com/api/v2.3.0/en/folktale.result.fromnullable.html (where it is called feedbackValue)
My question is, if I pass a feedbackValue (using docs naming) to nullableToResult and after that call getOrElse this feedbackValue will be overridden by getOrElse's argument, why then, we are forced to pass a feedbackValue in nullableToResult?
edgarjrg
@edgarjrg
Hi! My name is Edgar, and i have a doubt, i want to combine folktales Result with redux-saga, but doing .matchWithinvokes the functions inside instead of returning a function (that happens to be a generator) is there a way to use .chain, .matchWith with generators - "redux-saga" ?
edgarjrg
@edgarjrg
i saw that i could use yield* r.matchWith({Ok: function* () {},Error: function* () {}}) and works fine
Matheus Ashton Silva
@ashton
yep, you can return generators in the pattern matching so, the matchWith call will return a generator
Gerald
@jk121960
Hi everyone, and thanks in advance for any help, I was wondering if someone would know why when using the .ap of the validation monad, on the third sequenced predicate it starts passing the target value rather than the monad carrying the function to the map portion. The first two work fine but on the third it throws an error. This is on the construct to check for errors and aggregate them. I can post a sample code block
here is a sample code block
        var isDataValid = function( target ) {
            return Validation.Success( function( a ) {
                return function( b ) {
                    return target;
                }
            } )
                .ap( isEventAndYearSegmentSelected( target ) )
                .ap( isIncomeAccountRelevant( target ) )
                .ap( isExpenseAccountRelevant( target ) )
        };
Quil
@robotlolita

@JesterXL more than 3 times at this point, but I'm hoping to publish a series of articles explaining what Purr is, how you program in it, and the development plan 'til the end of this month. I haven't had much time lately to work on things because I'm moving and dealing with immigration stuff and the like has been taking all my time.

The current model is much simpler than the old ones, and it has both gradual types and contracts. As for platforms, the idea is having a stand-alone programming platform with different runtimes you can deploy to without having to rewrite things. Currently Node, Electron, and web runtimes are planned. I want to experiment with a .NET runtime in the future if they release CoreRT, since that lets you ship super small cross-platform native applications. This means that you should be able to write a GUI application and deploy it in the browser, Electron, or as a native app without changing anything in your code.

Gerald
@jk121960
@robotlolita or anyone for that matter, Thanks, if you have a moment, what would be the correct way to approach a logical disjunction, not about success or fail but for flow control, as in a logic branch, thanks for any help.
Quil
@robotlolita
@jk121960 can you give an example code? I'd generally say "go with a simple if/else structure" but I'm not sure if there might be something more to it.
Gerald
@jk121960
@robotlolita Hi and thanks, I wanted to be able to based on circumstances execute one side of the flow or the other, not just a simple decision. I am learning FP by immersing myself in the constructs, I want to learn how to work without if/else except in limited circumstances. The platform I am on doesn't have block level variables yet, so no "let" although we have "const", I like the idea of keeping the data in a monad and working with it there if at all possible. A closed monadic approach to a flow decision is what I was talking about, so depending on circumstances, execute this function and flow or this function and flow. Hope that clarifies the question. Thanks again.
Quil
@robotlolita

@jk121960 I think the idea of avoiding if/else in general is misguided. It's the simplest thing that works, and it's the best construct for a lot of problems. You'll see it often in mathematics too (though generally expressed f(a) = b, if c; otherwise d).

There are particular constructs and ideas that, for limited domains, work better than generic branching. For example, the Validation applicative works better for validation than using generic branching—but it's only for validation, you can't really apply that to any other domain. Or the fail-fast approach some monads provide under .chain(), which gives you a sorta railway-oriented programming style.

You can make if/else a function if you want, so you could write: wrap(thing).andThen(f).andThen(choose(isAcceptable, doA, doB)).andThen(moreThingsGoHere), though I particularly think andThen(x => isAcceptable(x) ? doA() : doB()) is clearer and just as concise.

Gerald
@jk121960
@robotlolita Great, thanks for taking the time, I always enjoy your insight, your folktale docs and blogs had a great impact on my thinking as I come from an Object Oriented/Imperative background. Monads were like a revelation to me and I haven't looked back since then. Thanks again
Nathan
@nspaeth
Hi, I'm trying to put together a comparison of javascript functional programming libraries. Would someone very familiar with the project be willing to fill out a form answering a few questions for me? The Google Form is here..
Galileo Sanchez
@galileopy
Thanks everyone for the awesome library, I use it everyday, and thought that you deserve to know that at least one programmer is happier because of you. :)
I do find very useful the adt/union module to build custom union types to be used as actions in react/redux
It worries me a little bit though that it is still experimental :)
Riccardo Agnoletto
@Trebh

Hello good people, I'm trying the tstypes version of folktale, and was wandering if/how can I import the Task type definition so that I can use it as a return type for some functions of mine.

Things like this:

import {concurrency} from 'folktale';

and then trying to use concurrency.task as a typescript type seem to fail... I feel like I'm missing something obvious

Quil
@robotlolita
@Trebh "tstypes version of folktale"? Right now there isn't any official release of Folktale supporting TypeScript. If you're using a separate package's typings I guess you'd have to look at how they decided to implement it.
(There's work in progress for moving folktale to typescript, but I haven't been able to work on it for the last year as I was relocating to Sweden. Still dealing with relocation stuff actually)