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
};
Curiously, non-partial functions with the
Partialconstraint added to them do result in TCO.The following example is inspired by a Slack post by @natefaubion
which compiles to the following javascript: