// Generated by purs version 0.14.5
"use strict";
var Control_Applicative = require("../Control.Applicative/index.js");
var Control_Apply = require("../Control.Apply/index.js");
var Control_Bind = require("../Control.Bind/index.js");
var Control_Category = require("../Control.Category/index.js");
var Control_Monad = require("../Control.Monad/index.js");
var Control_Monad_Rec_Class = require("../Control.Monad.Rec.Class/index.js");
var Data_CatList = require("../Data.CatList/index.js");
var Data_Either = require("../Data.Either/index.js");
var Data_Eq = require("../Data.Eq/index.js");
var Data_Foldable = require("../Data.Foldable/index.js");
var Data_Function = require("../Data.Function/index.js");
var Data_Functor = require("../Data.Functor/index.js");
var Data_Maybe = require("../Data.Maybe/index.js");
var Data_Monoid = require("../Data.Monoid/index.js");
var Data_Ord = require("../Data.Ord/index.js");
var Data_Ordering = require("../Data.Ordering/index.js");
var Data_Semigroup = require("../Data.Semigroup/index.js");
var Data_Traversable = require("../Data.Traversable/index.js");
var Unsafe_Coerce = require("../Unsafe.Coerce/index.js");
var ExpF = function (x) {
    return x;
};
var Free = (function () {
    function Free(value0, value1) {
        this.value0 = value0;
        this.value1 = value1;
    };
    Free.create = function (value0) {
        return function (value1) {
            return new Free(value0, value1);
        };
    };
    return Free;
})();
var Return = (function () {
    function Return(value0) {
        this.value0 = value0;
    };
    Return.create = function (value0) {
        return new Return(value0);
    };
    return Return;
})();
var Bind = (function () {
    function Bind(value0, value1) {
        this.value0 = value0;
        this.value1 = value1;
    };
    Bind.create = function (value0) {
        return function (value1) {
            return new Bind(value0, value1);
        };
    };
    return Bind;
})();
var toView = function ($copy_v) {
    var $tco_done = false;
    var $tco_result;
    function $tco_loop(v) {
        var runExpF = function (v2) {
            return v2;
        };
        var concatF = function (v2) {
            return function (r) {
                return new Free(v2.value0, Data_Semigroup.append(Data_CatList.semigroupCatList)(v2.value1)(r));
            };
        };
        if (v.value0 instanceof Return) {
            var v2 = Data_CatList.uncons(v.value1);
            if (v2 instanceof Data_Maybe.Nothing) {
                $tco_done = true;
                return new Return(v.value0.value0);
            };
            if (v2 instanceof Data_Maybe.Just) {
                $copy_v = concatF(runExpF(v2.value0.value0)(v.value0.value0))(v2.value0.value1);
                return;
            };
            throw new Error("Failed pattern match at Control.Monad.Free (line 227, column 7 - line 231, column 64): " + [ v2.constructor.name ]);
        };
        if (v.value0 instanceof Bind) {
            $tco_done = true;
            return new Bind(v.value0.value0, function (a) {
                return concatF(v.value0.value1(a))(v.value1);
            });
        };
        throw new Error("Failed pattern match at Control.Monad.Free (line 225, column 3 - line 233, column 56): " + [ v.value0.constructor.name ]);
    };
    while (!$tco_done) {
        $tco_result = $tco_loop($copy_v);
    };
    return $tco_result;
};
var runFreeM = function (dictFunctor) {
    return function (dictMonadRec) {
        return function (k) {
            var go = function (f) {
                var v = toView(f);
                if (v instanceof Return) {
                    return Data_Functor.map((((dictMonadRec.Monad0()).Bind1()).Apply0()).Functor0())(Control_Monad_Rec_Class.Done.create)(Control_Applicative.pure((dictMonadRec.Monad0()).Applicative0())(v.value0));
                };
                if (v instanceof Bind) {
                    return Data_Functor.map((((dictMonadRec.Monad0()).Bind1()).Apply0()).Functor0())(Control_Monad_Rec_Class.Loop.create)(k(Data_Functor.map(dictFunctor)(v.value1)(v.value0)));
                };
                throw new Error("Failed pattern match at Control.Monad.Free (line 194, column 10 - line 196, column 37): " + [ v.constructor.name ]);
            };
            return Control_Monad_Rec_Class.tailRecM(dictMonadRec)(go);
        };
    };
};
var runFree = function (dictFunctor) {
    return function (k) {
        var go = function ($copy_f) {
            var $tco_done = false;
            var $tco_result;
            function $tco_loop(f) {
                var v = toView(f);
                if (v instanceof Return) {
                    $tco_done = true;
                    return v.value0;
                };
                if (v instanceof Bind) {
                    $copy_f = k(Data_Functor.map(dictFunctor)(v.value1)(v.value0));
                    return;
                };
                throw new Error("Failed pattern match at Control.Monad.Free (line 178, column 10 - line 180, column 33): " + [ v.constructor.name ]);
            };
            while (!$tco_done) {
                $tco_result = $tco_loop($copy_f);
            };
            return $tco_result;
        };
        return go;
    };
};
var resume$prime = function (k) {
    return function (j) {
        return function (f) {
            var v = toView(f);
            if (v instanceof Return) {
                return j(v.value0);
            };
            if (v instanceof Bind) {
                return k(v.value0)(v.value1);
            };
            throw new Error("Failed pattern match at Control.Monad.Free (line 213, column 17 - line 215, column 20): " + [ v.constructor.name ]);
        };
    };
};
var resume = function (dictFunctor) {
    return resume$prime(function (g) {
        return function (i) {
            return new Data_Either.Left(Data_Functor.map(dictFunctor)(i)(g));
        };
    })(Data_Either.Right.create);
};
var fromView = function (f) {
    return new Free(f, Data_CatList.empty);
};
var wrap = function (f) {
    return fromView(new Bind(f, Unsafe_Coerce.unsafeCoerce));
};
var suspendF = function (dictApplicative) {
    return function (f) {
        return wrap(Control_Applicative.pure(dictApplicative)(f));
    };
};
var freeMonad = {
    Applicative0: function () {
        return freeApplicative;
    },
    Bind1: function () {
        return freeBind;
    }
};
var freeFunctor = {
    map: function (k) {
        return function (f) {
            return Control_Bind.bindFlipped(freeBind)((function () {
                var $119 = Control_Applicative.pure(freeApplicative);
                return function ($120) {
                    return $119(k($120));
                };
            })())(f);
        };
    }
};
var freeBind = {
    bind: function (v) {
        return function (k) {
            return new Free(v.value0, Data_CatList.snoc(v.value1)(k));
        };
    },
    Apply0: function () {
        return freeApply;
    }
};
var freeApply = {
    apply: Control_Monad.ap(freeMonad),
    Functor0: function () {
        return freeFunctor;
    }
};
var freeApplicative = {
    pure: function ($121) {
        return fromView(Return.create($121));
    },
    Apply0: function () {
        return freeApply;
    }
};
var semigroupFree = function (dictSemigroup) {
    return {
        append: Control_Apply.lift2(freeApply)(Data_Semigroup.append(dictSemigroup))
    };
};
var freeMonadRec = {
    tailRecM: function (k) {
        return function (a) {
            return Control_Bind.bind(freeBind)(k(a))(function (v) {
                if (v instanceof Control_Monad_Rec_Class.Loop) {
                    return Control_Monad_Rec_Class.tailRecM(freeMonadRec)(k)(v.value0);
                };
                if (v instanceof Control_Monad_Rec_Class.Done) {
                    return Control_Applicative.pure(freeApplicative)(v.value0);
                };
                throw new Error("Failed pattern match at Control.Monad.Free (line 86, column 26 - line 88, column 21): " + [ v.constructor.name ]);
            });
        };
    },
    Monad0: function () {
        return freeMonad;
    }
};
var liftF = function (f) {
    return fromView(new Bind(f, (function () {
        var $122 = Control_Applicative.pure(freeApplicative);
        return function ($123) {
            return $122($123);
        };
    })()));
};
var freeMonadTrans = {
    lift: function (dictMonad) {
        return liftF;
    }
};
var monoidFree = function (dictMonoid) {
    return {
        mempty: Control_Applicative.pure(freeApplicative)(Data_Monoid.mempty(dictMonoid)),
        Semigroup0: function () {
            return semigroupFree(dictMonoid.Semigroup0());
        }
    };
};
var substFree = function (k) {
    var go = function (f) {
        var v = toView(f);
        if (v instanceof Return) {
            return Control_Applicative.pure(freeApplicative)(v.value0);
        };
        if (v instanceof Bind) {
            return Control_Bind.bind(freeBind)(k(v.value0))(Data_Functor.map(Data_Functor.functorFn)(go)(v.value1));
        };
        throw new Error("Failed pattern match at Control.Monad.Free (line 168, column 10 - line 170, column 33): " + [ v.constructor.name ]);
    };
    return go;
};
var hoistFree = function (k) {
    return substFree(function ($124) {
        return liftF(k($124));
    });
};
var foldableFree = function (dictFunctor) {
    return function (dictFoldable) {
        return {
            foldMap: function (dictMonoid) {
                return function (f) {
                    var go = (function () {
                        var $125 = resume(dictFunctor);
                        return function ($126) {
                            return (function (v) {
                                if (v instanceof Data_Either.Left) {
                                    return Data_Foldable.foldMap(dictFoldable)(dictMonoid)(go)(v.value0);
                                };
                                if (v instanceof Data_Either.Right) {
                                    return f(v.value0);
                                };
                                throw new Error("Failed pattern match at Control.Monad.Free (line 93, column 21 - line 95, column 21): " + [ v.constructor.name ]);
                            })($125($126));
                        };
                    })();
                    return go;
                };
            },
            foldl: function (f) {
                var go = function (r) {
                    var $127 = resume(dictFunctor);
                    return function ($128) {
                        return (function (v) {
                            if (v instanceof Data_Either.Left) {
                                return Data_Foldable.foldl(dictFoldable)(go)(r)(v.value0);
                            };
                            if (v instanceof Data_Either.Right) {
                                return f(r)(v.value0);
                            };
                            throw new Error("Failed pattern match at Control.Monad.Free (line 98, column 23 - line 100, column 23): " + [ v.constructor.name ]);
                        })($127($128));
                    };
                };
                return go;
            },
            foldr: function (f) {
                var go = function (r) {
                    var $129 = resume(dictFunctor);
                    return function ($130) {
                        return (function (v) {
                            if (v instanceof Data_Either.Left) {
                                return Data_Foldable.foldr(dictFoldable)(Data_Function.flip(go))(r)(v.value0);
                            };
                            if (v instanceof Data_Either.Right) {
                                return f(v.value0)(r);
                            };
                            throw new Error("Failed pattern match at Control.Monad.Free (line 103, column 23 - line 105, column 23): " + [ v.constructor.name ]);
                        })($129($130));
                    };
                };
                return go;
            }
        };
    };
};
var traversableFree = function (dictTraversable) {
    return {
        traverse: function (dictApplicative) {
            return function (f) {
                var go = (function () {
                    var $131 = resume(dictTraversable.Functor0());
                    return function ($132) {
                        return (function (v) {
                            if (v instanceof Data_Either.Left) {
                                return Data_Functor.map((dictApplicative.Apply0()).Functor0())((function () {
                                    var $133 = Control_Bind.join(freeBind);
                                    return function ($134) {
                                        return $133(liftF($134));
                                    };
                                })())(Data_Traversable.traverse(dictTraversable)(dictApplicative)(go)(v.value0));
                            };
                            if (v instanceof Data_Either.Right) {
                                return Data_Functor.map((dictApplicative.Apply0()).Functor0())(Control_Applicative.pure(freeApplicative))(f(v.value0));
                            };
                            throw new Error("Failed pattern match at Control.Monad.Free (line 110, column 21 - line 112, column 30): " + [ v.constructor.name ]);
                        })($131($132));
                    };
                })();
                return go;
            };
        },
        sequence: function (dictApplicative) {
            return function (tma) {
                return Data_Traversable.traverse(traversableFree(dictTraversable))(dictApplicative)(Control_Category.identity(Control_Category.categoryFn))(tma);
            };
        },
        Functor0: function () {
            return freeFunctor;
        },
        Foldable1: function () {
            return foldableFree(dictTraversable.Functor0())(dictTraversable.Foldable1());
        }
    };
};
var foldFree = function (dictMonadRec) {
    return function (k) {
        var go = function (f) {
            var v = toView(f);
            if (v instanceof Return) {
                return Data_Functor.map((((dictMonadRec.Monad0()).Bind1()).Apply0()).Functor0())(Control_Monad_Rec_Class.Done.create)(Control_Applicative.pure((dictMonadRec.Monad0()).Applicative0())(v.value0));
            };
            if (v instanceof Bind) {
                return Data_Functor.map((((dictMonadRec.Monad0()).Bind1()).Apply0()).Functor0())(function ($135) {
                    return Control_Monad_Rec_Class.Loop.create(v.value1($135));
                })(k(v.value0));
            };
            throw new Error("Failed pattern match at Control.Monad.Free (line 158, column 10 - line 160, column 37): " + [ v.constructor.name ]);
        };
        return Control_Monad_Rec_Class.tailRecM(dictMonadRec)(go);
    };
};
var eqFree = function (dictFunctor) {
    return function (dictEq1) {
        return function (dictEq) {
            return {
                eq: function (x) {
                    return function (y) {
                        var v = resume(dictFunctor)(y);
                        var v1 = resume(dictFunctor)(x);
                        if (v1 instanceof Data_Either.Left && v instanceof Data_Either.Left) {
                            return Data_Eq.eq1(dictEq1)(eqFree(dictFunctor)(dictEq1)(dictEq))(v1.value0)(v.value0);
                        };
                        if (v1 instanceof Data_Either.Right && v instanceof Data_Either.Right) {
                            return Data_Eq.eq(dictEq)(v1.value0)(v.value0);
                        };
                        return false;
                    };
                }
            };
        };
    };
};
var ordFree = function (dictFunctor) {
    return function (dictOrd1) {
        return function (dictOrd) {
            return {
                compare: function (x) {
                    return function (y) {
                        var v = resume(dictFunctor)(y);
                        var v1 = resume(dictFunctor)(x);
                        if (v1 instanceof Data_Either.Left && v instanceof Data_Either.Left) {
                            return Data_Ord.compare1(dictOrd1)(ordFree(dictFunctor)(dictOrd1)(dictOrd))(v1.value0)(v.value0);
                        };
                        if (v1 instanceof Data_Either.Left) {
                            return Data_Ordering.LT.value;
                        };
                        if (v instanceof Data_Either.Left) {
                            return Data_Ordering.GT.value;
                        };
                        if (v1 instanceof Data_Either.Right && v instanceof Data_Either.Right) {
                            return Data_Ord.compare(dictOrd)(v1.value0)(v.value0);
                        };
                        throw new Error("Failed pattern match at Control.Monad.Free (line 56, column 17 - line 60, column 36): " + [ v1.constructor.name, v.constructor.name ]);
                    };
                },
                Eq0: function () {
                    return eqFree(dictFunctor)(dictOrd1.Eq10())(dictOrd.Eq0());
                }
            };
        };
    };
};
var eq1Free = function (dictFunctor) {
    return function (dictEq1) {
        return {
            eq1: function (dictEq) {
                return Data_Eq.eq(eqFree(dictFunctor)(dictEq1)(dictEq));
            }
        };
    };
};
var ord1Free = function (dictFunctor) {
    return function (dictOrd1) {
        return {
            compare1: function (dictOrd) {
                return Data_Ord.compare(ordFree(dictFunctor)(dictOrd1)(dictOrd));
            },
            Eq10: function () {
                return eq1Free(dictFunctor)(dictOrd1.Eq10());
            }
        };
    };
};
module.exports = {
    suspendF: suspendF,
    wrap: wrap,
    liftF: liftF,
    hoistFree: hoistFree,
    foldFree: foldFree,
    substFree: substFree,
    runFree: runFree,
    runFreeM: runFreeM,
    resume: resume,
    "resume'": resume$prime,
    eqFree: eqFree,
    eq1Free: eq1Free,
    ordFree: ordFree,
    ord1Free: ord1Free,
    freeFunctor: freeFunctor,
    freeBind: freeBind,
    freeApplicative: freeApplicative,
    freeApply: freeApply,
    freeMonad: freeMonad,
    freeMonadTrans: freeMonadTrans,
    freeMonadRec: freeMonadRec,
    foldableFree: foldableFree,
    traversableFree: traversableFree,
    semigroupFree: semigroupFree,
    monoidFree: monoidFree
};
