You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// data Par f a where// Pure :: {x :: a} -> Par f a// Lift :: {i :: f a} -> Par f a// Ap :: {f :: Par f (a -> b), x :: Par f a} -> Par f b// TypeRep f = { of :: forall a. a -> f a}// foldPar :: (Applicative g) => Par f a ~> (Ɐ x. f x -> g x, TypeRep g) -> g afoldPar(f,T){// `argsF` contains Par structures which will eventually be applied to some functionconstargsF=[this/*:: Par f a */]// `fns` contains Par structures which resolve to some functionconstfns=[]// we have a loop which runs until we have something to return while(true){// we pop last Par object from `argsF` // we have guaranty that argsF will not be empty hereletargF=argsF.pop()// if the `argF` is `Ap` nodeif(Ap.is(argF)){// we get length of argsF {{{{{{{TK add why}}}}}}}constlengthInitial=argsF.length// until `argF` is `Ap`while(Ap.is(argF)){// so Ap node of type `Par f b` has structure like this:// {f :: Par f (a -> b), x :: Par f a}// so here we try to go dig into `f` part to be able to obtain // function `a -> b` and in this process we push the `x :: Par f a`// to `argsF` so if initially `` looked like :// argsF = [Ap(Ap(Pure(x => y => x + y), Pure(1)), Pure(2))]// fns = []// after this loop ends we would have// argsF = [Pure(2), Pure(1)]// argF = Pure(x => y => x + y)argsF.push(argF.x)argF=argF.f}// now as we went as deep as possible in `f` branch of `Ap` node `argF`// is either `Pure` node with function or `Lift` with some instruction// in both cases we now need to interpret it i.e create pure value in target// structure using `of(val, T)` or cal `f` with instruction which will return// interpret the instruction into target structure. in both cases they will // eventually produce some function for which we have arguments in `argsF`// so `foldArg(argF, f, T)` transforms `Free f (a -> b)` into `g (a -> b)`// and then we create the internal object which contains the `g (a -> b)` and// number of arguments it needs to take by diffing initial length of argsF // (which was 0 for the example case 2 so length will be 2) with current length// if `f = x => new Identity(x)) and `T.of = f` then // fns at this point will be `[Identity(x => y => x + y)]`fns.push(Fn(foldArg(argF,f,T),argsF.length-lengthInitial))// at this point we have "consumed" top `Ap` node from `argsF` and we `continue`// if there will be `Ap` nodes in the `argsF` this part will try to simplify// again and againcontinue}// at this point argT is not Ap node so it's either Pure or Lift which we can// interpret into g as we did in `Ap` caseconstargT=foldArg(argF,f,T)// if `fns` is empty this means we are done and we return argTif(fns.length===0){returnargT}// at this point we must have a function in fns which we popletfn=fns.pop()// and we apply `argT :: g a` to `fn :: g (a -> b)` and we will get `g b`letres=ap(fn.f,argT)// we check how meny times we needed to apply to the `fn`// if it's more then 1 then the `res` contains function (curried) which // wants to take more arguments which would be in the `argsF`if(fn.length>1){// so we need to push the `res` to the `fns` but with smaller `length`// and continue everythingfns.push(Fn(res,fn.length-1))continue}// at this point the `fn` has no more arguments so we check if there are other// Par objects which evaluate to some function in `fns` and if we have onewhile(fns.length>0){// we pop it from the `fns`fn=fns.pop()// and apply `res` to itres=ap(fn.f,res)// here we check if result will need more argumentsif(fn.length>1){// in which case we push it to the `fns` with smaller `length`fns.push(Fn(res,fn.length-1))break}}// if we reach this position then and `fns` is emptyif(fns.length===0){// then we are done 🎉returnres}}}// Internal helper function for foldPar it folds only Pure and Lift nodesconstfoldArg=(node,f,T)=>{// check if `node` is `Pure` node and if soif(Pure.is(node)){// take it's pure value and put it in T// i.e. call `pure`/`return` of the target structurereturnof(T,node.x)// if `node` is `Lift` node then}elseif(Lift.is(node)){// we call `f` with instruction contained in the `Lift` node// with interprets the instruction into target structure and we return itreturnf(node.i)}}// Internal helper structure for foldPar it contains an Applicative containing// a function and information on how many argument it needs// type Fn g a b = { fun:: g (a -> b), length:: Number}constFn=(f,length)=>({ f, length })
typelevel/cats#1151 (comment)
The text was updated successfully, but these errors were encountered: