Syntactically light-weight call-by-name arguments in PureScript. No guarantees. Completely gratuitous.
This library takes advantage of term-abstraction incurred by type class
dictionaries to approximate call-by-name evaluation for arguments. We
simulate call-by-name by taking a
Unit -> a argument which defers evaluation
a until invoked. We then provide operators to coerce these
type-class-abstracted terms into the more reliable call-by-name form.
when function from
when :: forall m. Applicative m => Boolean -> m Unit -> m Unit
It is strict in both arguments, so it will allocate the provided effect
even though it may be discarded. This can be problematic, especially if there
let bound values:
example = when that do let a = somethingExpensive 42 b = somethingElseExpensive a this a b
b will be evaluated, which we don't want. The alternative is to
use a call-by-name approximation:
when :: forall m. Applicative m => Boolean -> (Unit -> m Unit) -> m Unit example = when that \_ -> do let a = somethingExpensive 42 b = somethingElseExpensive a this a b
But wow that's irritating. This library exports an application operator
that makes this look better.
import CallByName.Applicative (when) import CallByName.Syntax ((\\)) example = when that \\do let a = somethingExpensive 42 b = somethingElseExpensive a this a b
We've saved four arduous characters.
There's also the
~ operator which lifts terms into
somethingLazy :: Lazy Int -> Int example = somethingLazy ~(evaluate expensive int)
Versus the old:
example = somethingLazy (Lazy.defer \_ -> evaluate expensive int)
This library also exports some call-by-name variants of functions that don't exist in current Prelude or ecosystem.
CallByName.Applicative.when :: forall m. Applicative m => Boolean -> (Unit -> m Unit) -> m Unit CallByName.Applicative.unless :: forall m. Applicative m => Boolean -> (Unit -> m Unit) -> m Unit CallByName.Monoid.guard :: forall m. Monoid m => Boolean -> (Unit -> m) -> m
And also exports a version of the
Alt type class which defers it's second
class Strict.Alt f <= Alt f where alt :: forall a. f a -> (Unit -> f a) -> f a
This can be combined with a magic, right-associated version of
does not strictly evaluate it's second argument.
example = Just 42 <|> unsafeThrow "Too strict!"