Is it considered valid for `Pair` to be an instance of `MonadRec`?

Phil Freeman's paper titled Stack Safety for Free introduces the MonadRec type class with the following definition.

class (Monad m) <= MonadRec m where
  tailRecM :: forall a b. (a -> m (Either a b)) -> a -> m b

Any instance of the MonadRec class must adhere to certain laws.

  1. tailRecM f a should be equal to f a >>= go where go (Left a) = f a >>= go and go (Right b) = pure b.
  2. The stack utilization of tailRecM f must not exceed a constant multiple of the stack usage by f itself.

Now, let's consider the Pair class in TypeScript.

class Pair<out A> {
  public constructor(
    public readonly fst: A,
    public readonly snd: A,
  ) {}

  public chain<A, B>(this: Pair<A>, arrow: (value: A) => Pair<B>): Pair<B> {
    return new Pair(arrow(this.fst).fst, arrow(this.snd).snd);
  }

  public static of<A>(value: A): Pair<A> {
    return new Pair(value, value);
  }
}

The implementation of chainRec for Pair, which is equivalent to Phil Freeman's tailRecM, involves defining an Either type first in TypeScript.

class Left<out A> {
  public readonly isLeft = true;

  public constructor(public readonly value: A) {}
}

class Right<out B> {
  public readonly isLeft = false;

  public constructor(public readonly value: B) {}
}

type Either<A, B> = Left<A> | Right<B>;

Then, the chainRec function is implemented within the Pair class as shown below.

public static chainRec<A, B>(
  arrow: (value: A) => Pair<Either<A, B>>,
  value: A,
): Pair<B> {
  // Implementation omitted for brevity
}

You can test this implementation using the provided Fantasy Land Playground Link.

In terms of adhering to the laws, while it's evident that the first law is satisfied, concerns arise regarding the second one.

  • The stack utilization of Pair.chainRec(f, a) must not surpass a fixed multiple of the stack usage by f.

Regarding the second law, there may be uncertainties due to the potentially unbounded growth of the local stack variable within the rec function. This prompts questions on whether allowing chainRec to use such a large local stack could enable creating valid instances of MonadRec for any monad. If not, examples of monads that are valid Monad instances but not MonadRec instances would provide clarity on non-tail recursive monads.

Answer №1

Absolutely, I fully anticipate the Pair monad to be capable of handling stack overflow and implementing a precise tailRecM method.

One way to argue this is by considering that the Pair monad can be seen as a unique form of the Reader monad:

 type Reader r a = r -> a

If we assign r = Bool, then the type Bool -> a is essentially the same as the pair (a, a). In essence, Pair a is equivalent to Reader Bool a.

The Reader r monad guarantees stack safety for any given type r, along with its standard tailRecM operation. This function from Reader can be specialized by setting r = Bool, resulting in a valid implementation of tailRecM for Pair.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to loop through a formarray and assign its values to a different array in TypeScript?

Within my form, I have a FormArray with a string parameter called "Foo". In an attempt to access it, I wrote: let formArray = this.form.get("Foo") as FormArray; let formArrayValues: {Foo: string}[]; //this data will be incorporated into the TypeScript mod ...

Showing Arrays in Angular on HTML Page

I have created an array that stores multiple arrays with 3 indexes each. An example of the structure looks like this: (3) [Array(3), Array(3), Array(3)] 0: (3) [199.4, 10.5, 19] 1: (3) [47.2, 2.1, 23] 2: (3) [133.6, 5.3, 25] In my HTML, I want to display ...

Blank webpage caused by ngx TranslateService

Every time I attempt to translate Angular components using ngx-translate/core by utilizing the translateService in the constructor, the page appears blank. This is my appModule : import { NgModule } from '@angular/core'; import { BrowserModule } ...

Problem with Typescript and packages.json file in Ionic 3 due to "rxjs" issue

I encountered a series of errors in my Ionic 3 project after running ionic serve -l in the command terminal. The errors are detailed in the following image: Errors in picture: https://i.sstatic.net/h3d1N.jpg Full errors text: Typescript Error ';& ...

Guide to resolving the unsubscribe issue in Angular

TS tempThermometer = new BehaviorSubject<any>([]); subscription: Subscription; const promises = list.map( (url: any) => new Promise(resolve => { this.subscription = this.global.getData(url.link).pipe(ta ...

Efficiently loading children components through lazy loading

My component was functioning perfectly until I added a heavy children component that caused the page to freeze. Now I am considering implementing lazy loading for the children component. Is this the correct solution? Additionally, I want to ensure that th ...

The 'DOCUMENT' module (imported as 'i23') could not be located within '@angular/platform-browser'

During my upgrade from Angular version 7 to 8, I encountered an error when building the project even though I am not using DOCUMENT. It seems like something is causing this issue that I am overlooking. I have thoroughly checked all the files and confirmed ...

What could be causing this TypeScript code to not pass typechecking?

defining two objects in TypeScript with different property sets and assigning them to each other. Link to more information ...

Encountering 404 errors when reloading routes on an Angular Azure static web app

After deploying my Angular app on Azure static web app, I encountered an error. Whenever I try to redirect to certain routes, it returns a 404 error. However, if I navigate from one route to another within the app, everything works fine. I have attempted t ...

Tips for making use of incomplete types

Is there a way to reference a type in TypeScript without including all of its required fields, without creating a new interface or making all fields optional? Consider the following scenario: interface Test { one: string; two: string; } _.findWhe ...

Resolving the Angular NG0100 Error: Troubleshooting the ExpressionChangedAfterItHasBeenCheckedError

I am currently working on implementing a dialog component that takes in data through its constructor and then utilizes a role-based system to determine which parts of the component should be displayed. The component code snippet looks like this: export cl ...

What does `(keyof FormValues & string) | string` serve as a purpose for?

Hey there! I'm new to TypeScript and I'm a bit confused about the purpose of (keyof FormValues & string) | string. Can someone please explain it to me? export type FieldValues = Record<string, any>; export type FieldName<FormValues ...

When using `type B = A`, B is represented as A. However, if `type B = A | A` is utilized, B appears as 'any'. What causes this change in representation?

import { C } from "https://example.com/type.d.ts"; type D = C | C Playground Upon hovering over D in both the TS Playground and VS Code, it will show as C when declared as type D = C, but display any when declared as type D = C | C. Even if C&a ...

Cross-component communication in Angular

I'm currently developing a web-based application using angular version 6. Within my application, there is a component that contains another component as its child. In the parent component, there is a specific function that I would like to invoke when ...

Translating a C# ViewModel into TypeScript

Here is a C# viewmodel example: public class LoginModel { [Required(ErrorMessage = "Email is not specified")] public string Email { get; set; } [Required(ErrorMessage = "No password is specified")] [DataType(DataType.Password)] public ...

Tips for showcasing a string value across various lines within a paragraph using the <br> tag for line breaks

I'm struggling to show a string in a paragraph that includes tags to create new lines. Unfortunately, all I see is the br tags instead of the desired line breaks. Here is my TypeScript method. viewEmailMessage(messageId: number): void { c ...

Having trouble establishing a connection with SignalR on my backend, it just doesn't seem to work properly

I am currently working on a project where I am using Vue with TypeScript and @microsoft/signalr. My goal is to create a chat feature using SignalR, and on the backend, I am utilizing C# with ASP.NET Core and docker. Here is the code snippet I have impleme ...

Create multiple instances of a component in a dropdown menu using different datasets in Angular 5

Outlined below is the structure of my drop-down list: Companies > Depots Each company has multiple depots. I have developed a component for companies, and upon clicking on a company (menu item), an HTTP request is made to bring all companies which are ...

Is there a way to retrieve a React.Component class by calling a function?

I came across this interesting post: How can I return a class from a TypeScript function? In the linked post above, there is an example of working code: export class Foo {} // Foo is exported export let factory = () : Foo => { // it could be return ty ...

What causes @typescript-eslint to retain old types/files in its cache and prevent successful compilation?

When I kick off my Typescript application using tsc -b -w, I always encounter an issue with @typescript-eslint not reacting to file changes accurately. It flags invalid types/syntax errors where there are none. Restarting the process sometimes doesn't ...