Crocks

  • Documentation
Docs Menu
  • Getting Started
  • Crocks
    • Arrow
    • Async
    • Const
    • Either
    • Equiv
    • Identity
    • Maybe
    • Pair
    • Pred
    • Reader
    • ReaderT
    • Result
    • State
    • Tuple
  • Monoids
    • All
    • Any
    • Assign
    • Endo
    • First
    • Last
    • Max
    • Min
    • Prod
    • Sum
  • Functions
    • Combinators
    • Helpers
    • Logic Functions
    • Predicate Functions
    • Point-free Functions
    • Transformation Functions

Pred

Pred a Boolean

Defined as a Monoidal Contravariant datatype, Pred wraps a predicate function of the form (a -> Boolean).

The far right parameter of Pred is always fixed to the type of Boolean, so the result of the wrapped predicate function can never be mapped. While the right parameter is fixed, the input to the predicate can vary.

Another property of Pred instances is that they can be combined using their Monodial interface. Combining instances will result in a new instance that returns the result of each Pred under logical conjunction.

As Pred wraps a function, it is lazy and will not execute until its argument is satisfied. A given instance is run but calling the runWithmethod, supplying it the argument to test.

One of the features of crocks is the ability to use both normal predicate functions and Pred instances interchangeably. For any crocks function that takes a predicate, either a predicate function or a Pred instance can be used.

This implementation of Pred was heavily inspired by this article.

import Pred from 'crocks/Pred'

import isNumber from 'crocks/predicates/isNumber'
import getPropOr from 'crocks/helpers/getPropOr'
import filter from 'crocks/pointfree/filter'

// largeNumber :: Pred Number
const largeNumber =
  Pred(isNumber)
    .concat(Pred(x => x > 100))

// largeItem :: Pred Object
const largeItem =
  largeNumber
    .contramap(getPropOr(null, 'item'))

largeNumber
  .runWith(45)
//=> false

largeNumber
  .runWith(175)
//=> true

largeItem
  .runWith({ item: 190 })
//=> true

largeItem
  .runWith({ item: 9 })
//=> false

largeItem
  .runWith(9)
//=> false

filter(largeNumber, [ 200, 375, 15 ])
//=> [ 200, 375 ]

Implements

Semigroup, Monoid, Contravariant

Construction

Pred :: (a -> Boolean) -> Pred a

The Pred constructor is a unary function that requires a unary predicate function as its sole argument. Once provided with its predicate function, the constructor will return a new Pred instance wrapping the predicate.

If the function provided is not a predicate, then the resulting value will be coerced to a Boolean.

import Pred from 'crocks/Pred'

import and from 'crocks/logic/and'
import isArray from 'crocks/predicates/isArray'

// isEmpty :: a -> Boolean
const isEmpty =
  x => !x.length

// isEmptyArray :: a -> Boolean
const isEmptyArray =
  and(isArray, isEmpty)

Pred(isEmptyArray)
//=> Pred a

Constructor Methods

empty

Pred.empty :: () -> Pred a

empty provides the identity for the Monoid in that when the value it provides is concated to any other value, it will return the other value. In the case of Pred the result of empty is a Pred that will always return true. empty is available on both the Constructor and the Instance for convenience.

import Pred from 'crocks/Pred'

import isEmpty from 'crocks/predicates/isEmpty'
import not from 'crocks/logic/not'

// empty :: Pred a
const empty =
  Pred.empty()

// notEmpty :: Pred a
const notEmpty =
  Pred(not(isEmpty))

empty
  .runWith('')
//=> true

notEmpty
  .concat(empty)
  .runWith([])
//=> false

notEmpty
  .concat(empty)
  .runWith([ 1, 2, 3 ])
//=> true

empty
  .concat(notEmpty)
  .runWith('')
//=> false

empty
  .concat(notEmpty)
  .runWith('123')
//=> true

Instance Methods

concat

Pred a ~> Pred a -> Pred a

concat is used to combine two Semigroups of the same type under an operation specified by the Semigroup. In the case of Pred, the results of both Predss are combined under logical conjunction.

import Pred from 'crocks/Pred'

import or from 'crocks/logic/or'
import not from 'crocks/logic/not'
import filter from 'crocks/pointfree/filter'

const isEven =
  x => !(x % 2)

// isOdd :: Pred Number
const isOdd =
  Pred(not(isEven))

// lt20 :: Pred Number
const lt20 =
  Pred(x => x < 20)

// gt5 :: Pred Number
const gt5 =
  Pred(x => x > 5)

// inRange :: Pred Number
const inRange =
  lt20.concat(gt5)

// isOddInRange :: Pred Number
const isOddInRange =
  isOdd.concat(inRange)

// isValid :: Pred Number
const isValid =
  Pred(or(isEven, isOddInRange))

// data :: [ Number ]
const data =
[ 1, 4, 12, 19, 32, 99, 76, 7 ]

isOdd
  .runWith(5)
//=> true

isOdd
  .runWith(8)
//=> false

filter(isOdd, data)
//=> [ 1, 19, 99, 7 ]

filter(lt20, data)
//=> [ 1, 4, 12, 19, 7 ]

filter(gt5, data)
//=> [ 12, 19, 32, 99, 76, 7 ]

filter(inRange, data)
//=> [ 12, 19, 7 ]

filter(isOddInRange, data)
//=> [ 19, 7 ]

filter(isEven, data)
// [ 4, 12, 32, 76 ]

filter(isValid, data)
//=> [ 4, 12, 19, 32, 76, 7 ]

contramap

Pred a ~> (b -> a) -> Pred b

While the output of a Pred is fixed to Boolean, the input can vary type and value. This allows a given Pred to be adapted by mapping on the input, before it hits the wrapped predicate function. Using contramap, functions are lifted, mapping the input to now accept the type of the input of the given function.

import Pred from 'crocks/Pred'
import contramap from 'crocks/pointfree/contramap'
import getPropOr from 'crocks/helpers/getPropOr'

// Length :: String | Function | Array
// length :: Length -> Number
const length =
  getPropOr(0, 'length')

// gt5 :: Pred Number
const gt5 =
  Pred(x => x > 5)

// lengthGt5 :: Pred Length
const validLength =
  contramap(length, gt5)

// validItemLength :: Pred Object
const validItemLength =
  contramap(getPropOr(null, 'item'), validLength)

gt5
  .runWith(5)
//=> false

gt5
  .runWith(10)
//=> true

validLength
  .runWith([ 1, 2, 3, 4, 5, 6 ])
//=> true

validLength
  .runWith(null)
//=> false

validLength
  .runWith('1234')
//=> false

validItemLength
  .runWith({ item: 'this is an item' })
//=> true

valueOf

Pred a ~> () -> a -> Boolean

valueOf is used on all crocks Monoids as a means of extraction. While the extraction is available, types that implement valueOf are not necessarily a Comonad. This function is used primarily for convenience for some of the helper functions that ship with crocks.

Calling valueOf on a Pred instance will result in the underlying predicate function. Most of the time this will not be required when working with crocks because all crocks functions that take a predicate function can also take a Pred instance.

import Pred from 'crocks/Pred'

import equals from 'crocks/pointfree/equals'
import isArray from 'crocks/predicates/isArray'
import isString from 'crocks/predicates/isString'
import or from 'crocks/logic/or'

// lengthIsThree :: Pred a
const lengthIsThree =
  Pred(equals(3))
    .contramap(x => x.length)

// pred :: Pred a
const pred =
  Pred(or(isArray, isString))
    .concat(lengthIsThree)

// fn :: a -> Boolean
const fn =
  pred.valueOf()

pred
  .runWith(null)
//=> false

pred
  .runWith([ 1, 2, 3 ])
//=> true

pred
  .runWith('This is fun')
//=> true

fn(null)          // false
fn([ 1, 2, 3 ])   // true
fn('This is fun') // true
fn([])            // false
fn('')            // false

runWith

Pred a ~> a -> Boolean

As Pred wraps a predicate function, it needs a mean to run it with some value to test against the predicate. Pred instances provide a method called runWith that will accept the value to be tested and then runs it through the predicate returning the result.

Most of the time this function is not used while working with other predicate functions in crocks, as all functions that take a predicate function also take a Pred instance. It does come in handy though when supplying predicates to other libraries.

import Pred from 'crocks/Pred'

import hasProp from 'crocks/predicates/hasProp'
import equals from 'crocks/pointfree/equals'
import flip from 'crocks/combinators/flip'
import runWith from 'crocks/pointfree/runWith'

// trueBlue :: Pred Object
const trueBlue =
  Pred(equals(true))
    .contramap(({ blue }) => blue)

// isValid :: Pred a
const isValid =
  Pred(hasProp('blue'))
    .concat(trueBlue)

// checkValid :: a -> Boolean
const checkValid =
  flip(runWith, isValid)

checkValid(null)            //=> false
checkValid([ 1, 2, 3 ])     //=> false
checkValid({ blue: 32 })    //=> false
checkValid({ blue: true })  //=> true

Contribute on Github! Edit this section.