Skip to content

Instantly share code, notes, and snippets.

@mishelashala
Created July 17, 2020 13:53
Show Gist options
  • Save mishelashala/ef10ae832f1b71c61ac7395cff4a730f to your computer and use it in GitHub Desktop.
Save mishelashala/ef10ae832f1b71c61ac7395cff4a730f to your computer and use it in GitHub Desktop.
const { compose, curry } = require('lodash/fp')
// Success :: a -> Success a
const Success = value => ({
type: 'success',
value
})
Success.is = obj => obj.type === 'success'
// Failure :: a -> Failure a
const Failure = value => ({
type: 'failure',
value
})
Failure.is = (obj) => obj.type === 'failure'
// validateUserName :: User -> Success User | Failure
const validateUserName = user => {
return !user.name
? Failure("Name is required")
: Success(user)
}
// validateUserAge :: User -> Success User | Failure
const validateAge = user => {
return user.age < 18
? Failure("User is underage")
: Success(user)
}
// bind :: (Success a -> Success a | Failure ) -> Success a -> Succes a | Failure
const bind = curry((fn, data) => {
if (Success.is(data)) {
return fn(data.value)
}
if (Failure.is(data)) {
return data
}
});
const john = {
name: "john doe",
age: 18
}
// incrementAge :: User -> User
const incrementAge = user => {
return {
...user,
age: user.age + 1
}
}
// map :: (a -> b) -> a -> Success a | Failure
const map = curry((fn, data) => {
if (Success.is(data)) {
return Success(fn(data.value))
}
if (Failure.is(data)) {
return data
}
})
// tee :: (a -> b) -> a -> a
const tee = curry((fn, data) => {
fn(data)
return data
})
// log :: a -> ()
const log = msg => {
console.log(msg)
}
// canDrinkAlcohol :: User -> User
const canDrinkAlcohol = user => {
if (user.age < 21) {
throw new Error("Cannot drink, is underage")
}
return user
}
// tryCatch :: (a -> b) -> Success a -> Success b | Failure
const tryCatch = curry((fn, data) => {
try {
return Success(fn(data.value))
} catch(err) {
return Failure(err.message)
}
})
// fold :: (a -> ()) -> (b -> ()) -> Success a | Failure -> ()
const fold = curry((success, failure, data) => {
if (Failure.is(data)) {
failure(data.value)
}
if (Success.is(data)) {
success(data.value)
}
})
const notifySuccess = data => {
console.log("success: ", data, " yay!")
}
const notifyFailure = msg => {
console.log("failure:", data, " nay!")
}
// validateUser :: User -> Success User | Failure string
const validateUser = compose(
fold(notifySuccess, notifyFailure),
tryCatch(canDrinkAlcohol),
map(incrementAge),
map(incrementAge),
map(incrementAge),
bind(validateAge),
validateUserName
)
validateUser(john)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment