Skip to content

Partial functions can foil TCO #3157

Description

@matthewleon

Curiously, non-partial functions with the Partial constraint added to them do result in TCO.

The following example is inspired by a Slack post by @natefaubion

module Tco where

import Data.List (List(..), (:))

tco :: Partial => List String -> String
tco ("" : _) = ""
tco (_ : xs) = tco xs
tco Nil = ""

notco :: Partial => List String -> String
notco ("" : _) = ""
notco (_ : xs) = notco xs

which compiles to the following javascript:

// Generated by purs version 0.11.7
"use strict";
var Data_List = require("../Data.List");
var Data_List_Types = require("../Data.List.Types");
var tco = function ($copy_dictPartial) {
    return function ($copy_v) {
        var $tco_var_dictPartial = $copy_dictPartial;
        var $tco_done = false;
        var $tco_result;
        function $tco_loop(dictPartial, v) {
            if (v instanceof Data_List_Types.Cons && v.value0 === "") {
                $tco_done = true;
                return "";
            };
            if (v instanceof Data_List_Types.Cons) {
                $tco_var_dictPartial = dictPartial;
                $copy_v = v.value1;
                return;
            };
            if (v instanceof Data_List_Types.Nil) {
                $tco_done = true;
                return "";
            };
            throw new Error("Failed pattern match at Tco line 5, column 1 - line 5, column 40: " + [ v.constructor.name ]);
        };
        while (!$tco_done) {
            $tco_result = $tco_loop($tco_var_dictPartial, $copy_v);
        };
        return $tco_result;
    };
};
var notco = function (dictPartial) {
    return function (v) {
        var __unused = function (dictPartial1) {
            return function ($dollar4) {
                return $dollar4;
            };
        };
        return __unused(dictPartial)((function () {
            if (v instanceof Data_List_Types.Cons && v.value0 === "") {
                return "";
            };
            if (v instanceof Data_List_Types.Cons) {
                return notco(dictPartial)(v.value1);
            };
            throw new Error("Failed pattern match at Tco line 10, column 1 - line 10, column 42: " + [ v.constructor.name ]);
        })());
    };
};
module.exports = {
    tco: tco,
    notco: notco
};

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions