Skip to content

Conversation

@williamareynolds
Copy link
Collaborator

In order to complete the instance of Applicative, a method "apply" must
be added to the type. Technically, a Monad does not require an instance
of Applicative, but most modern functional languages and libraries
enforce this constraint due to the benefits derived when implementing
instances of other Categories. Particularly in the case of Maybe, this
instance is desirable due to the behavior of Maybes which wrap a
function. Because applying an undefined function to a value results in
an error, rather than undefined or null, mapping a function wrapped by
Maybe demands that the function be unwrapped and coerced to some
default before it can be used, or checking to see if it is defined. The
"apply" method allows a value wrapped by Maybe to be applied to a
function wrapped by Maybe.

Example:

import { maybe, IMaybe } from 'typescript-monads'

declare f(): string | undefined
declare g(): string | undefined

const fileName = maybe(f())
const mirrorUrl = maybe(g())
const makeUrl = (fileName: string) => (url: string) => `${url}/${name}`

/*
 * Without Applicative, we wind up nesting maps
 */
const getMirror: IMaybe<(url: string) => string> = fileName.map(name => makeUrl(name))

const mirror: IMaybe<string> = mirrorUrl.flatMap(url => getMirror.map(f => f(url)))

/*
 * With Applicative, we can directly apply a potentially undefined function
 */
const getMirror: IMaybe<(url: string) => string> = fileName.map(name => makeUrl(name))

const mirror: IMaybe<string> = fileName.apply(getMirror)

In order to complete the instance of Applicative, a method "apply" must
be added to the type. Technically, a Monad does not require an instance
of Applicative, but most modern functional languages and libraries
enforce this constraint due to the benefits derived when implementing
instances of other Categories. Particularly in the case of Maybe, this
instance is desirable due to the behavior of Maybes which wrap a
function. Because applying an undefined function to a value results in
an error, rather than undefined or null, mapping a function wrapped by
Maybe demands that the function be unwrapped and coerced to some
default before it can be used, or checking to see if it is defined. The
"apply" method allows a value wrapped by Maybe to be applied to a
function wrapped by Maybe.
@patrickmichalina patrickmichalina changed the title fix(maybe): complete instance of applicative feat(maybe): complete instance of applicative Feb 1, 2020
Copy link
Owner

@patrickmichalina patrickmichalina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dope, thank you!

@patrickmichalina
Copy link
Owner

Try updating the branch with master and see if a build will work now - I changed the circle-ci settings.

@williamareynolds williamareynolds merged commit d681f42 into patrickmichalina:master Feb 1, 2020
@williamareynolds williamareynolds deleted the complete-applicative-instance branch February 1, 2020 22:12
@patrickmichalina
Copy link
Owner

🎉 This PR is included in version 3.13.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants