Realm v0.1.0 Realm View Source
A set of functions to mimic the standard Haskell libraries feature a number of type classes with algebraic or category-theoretic underpinnings. The functions in this module come in two flavors: named or operators. For example:
iex> use Realm
iex> append(1, 1) # named
2
iex> 1 <> 1 # operator
2
If you prefer to use only operators or skip them, you can pass the following options:
:only_operators
- includes only operators:skip_operators
- skips operators For example: iex> use Realm, onlyoperators: true iex> 1 <> 1 2 When invoked with no options,use Realm
is equivalent toimport Realm
. All bitwise functions can be used in guards: iex> appendable? = fn ...> semigroup when Realm.append(semigroup, 1) == 2 -> true ...> -> false ...> end iex> appendable?.(1) true
Link to this section Summary
Functions
The opposite of equivalent?/2
.
Duplicate incoming data into both halves of a 2-tuple, and run one function on the left copy, and a different function on the right copy.
Determine if an element is :lesser
than another.
Same as ap/2
, but with all functions curried.
Determine if an element is :lesser
or :equal
to another.
There is an operator alias a <> b
. Since this conflicts with Kernel.<>/2
,
use Realm,Semigroup
will automatically exclude the Kernel operator.
This is highly recommended, since <>
behaves the same on bitstrings, but is
now available on more datatypes.
lift/2
but with arguments flipped.
Determine if an element is equal to another.
Determine if an element is :greater
than another.
Determine if an element is :greater
or :equal
to another.
Take two arguments (as a 2-tuple), and run one function on the left side (first element), and run a different function on the right side (second element).
There is an operator alias a <> b
. Since this conflicts with Kernel.<>/2
,
use Realm,Semigroup
will automatically exclude the Kernel operator.
This is highly recommended, since <>
behaves the same on bitstrings, but is
now available on more datatypes.
Determine if an element is :greater
or :equal
to another.
Determine if an element is :lesser
or :equal
to another.
Composition operator "the math way". Alias for compose/2
.
Determine if an element is equal to another.
Duplicate incoming data into both halves of a 2-tuple, and run one function on the left copy, and a different function on the right copy.
Composition operator "the pipe way". Alias for compose/2
.
Determine if an element is :greater
than another.
Determine if an element is :lesser
than another.
map/2
but with the function automatically curried
The opposite of equivalent?/2
.
lift/2
but with arguments flipped.
Take two arguments (as a 2-tuple), and run one function on the left side (first element), and run a different function on the right side (second element).
Same as ap/2
, but with all functions curried.
Same as convey/2
, but with all functions curried.
map/2
but with the function automatically curried
Same as convey/2
, but with all functions curried.
Link to this section Functions
The opposite of equivalent?/2
.
Examples
iex> 1 != 2
true
left &&& right
View SourceRealm.Arrow.t() &&& Realm.Arrow.t() :: Realm.Arrow.t()
Duplicate incoming data into both halves of a 2-tuple, and run one function on the left copy, and a different function on the right copy.
┌------> f.(a) = x ------┐
| v
a ---> split = {a, a} {x, y}
| ^
└------> g.(a) = y ------┘
Examples
iex> fanned = fn x -> x - 10 end &&& fn y -> inspect(y) <> "!" end
...> fanned.(42)
{32, "42!"}
iex> fanned =
...> fn x -> x - 10 end
...> &&& fn y -> inspect(y) <> "!" end
...> &&& fn z -> inspect(z) <> "?" end
...> &&& fn d -> inspect(d) <> inspect(d) end
...> &&& fn e -> e / 2 end
...>
...> fanned.(42)
{{{{32, "42!"}, "42?"}, "4242"}, 21.0}
Determine if an element is :lesser
than another.
Examples
iex> 1 < 1
false
iex> 1 < 1.1
true
funs <<~ apply
View SourceRealm.Apply.t() <<~ Realm.Apply.t() :: Realm.Apply.t()
Same as ap/2
, but with all functions curried.
Examples
iex> [fn x -> x + 1 end, fn y -> y * 10 end] <<~ [1, 2, 3]
[2, 3, 4, 10, 20, 30]
iex> import Realm.Functor
...>
...> [100, 200]
...> ~> fn(x, y, z) -> x * y / z
...> end <<~ [5, 2]
...> <<~ [100, 50]
...> ~> fn x -> x + 1 end
[6.0, 11.0, 3.0, 5.0, 11.0, 21.0, 5.0, 9.0]
iex> import Realm.Functor, only: [<~: 2]
...> fn(a, b, c, d) -> a * b - c + d end <~ [1, 2] <<~ [3, 4] <<~ [5, 6] <<~ [7, 8]
[5, 6, 4, 5, 6, 7, 5, 6, 8, 9, 7, 8, 10, 11, 9, 10]
Determine if an element is :lesser
or :equal
to another.
Examples
iex> use Realm.Ord
...> 1 <= 2
true
...> [] <= [1, 2, 3]
false
...> [1] <= [1, 2, 3]
true
...> [4] <= [1, 2, 3]
false
left <> right
View SourceRealm.Semigroup.t() <> Realm.Semigroup.t() :: Realm.Semigroupoid.t()
There is an operator alias a <> b
. Since this conflicts with Kernel.<>/2
,
use Realm,Semigroup
will automatically exclude the Kernel operator.
This is highly recommended, since <>
behaves the same on bitstrings, but is
now available on more datatypes.
Examples
iex> use Realm.Semigroup
...> 1 <> 2 <> 3 <> 5 <> 7
18
iex> use Realm.Semigroup
...> [1, 2, 3] <> [4, 5, 6] <> [7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
iex> use Realm.Semigroup
...> "foo" <> " " <> "bar"
"foo bar"
g <|> f
View SourceRealm.Semigroupoid.t() <|> any() :: Realm.Semigroupoid.t()
Composition operator "the math way". Alias for compose/2
.
Examples
iex> times_ten_plus_one =
...> fn x -> x + 1 end
...> <|> fn y -> y * 10 end
...>
...> times_ten_plus_one.(5)
51
fun <~ functor
View Source(... -> any()) <~ Realm.Functor.t() :: Realm.Functor.t()
lift/2
but with arguments flipped.
iex> (fn x -> x + 5 end) <~ [1,2,3]
[6, 7, 8]
Note that the mnemonic is flipped from |>
, and combinging directions can
be confusing. It's generally recommended to use ~>
, or to keep <~
on
the same line both of it's arguments:
iex> fn(x, y) -> x + y end <~ [1, 2, 3]
...> |> List.first()
...> |> apply([9])
10
...or in an expression that's only pointing left:
iex> fn y -> y * 10 end
...> <~ fn x -> x + 55 end
...> <~ [1, 2, 3]
[560, 570, 580]
f <~> g
View SourceRealm.Semigroupoid.t() <~> any() :: Realm.Semigroupoid.t()
Composition operator "the pipe way". Alias for compose/2
.
Examples
iex> times_ten_plus_one =
...> fn y -> y * 10 end
...> <~> fn x -> x + 1 end
...>
...> times_ten_plus_one.(5)
51
Determine if an element is equal to another.
Examples
iex> use Realm.Ord
...> 2 == 1
false
...> 1 == 1
true
Determine if an element is :greater
than another.
Examples
iex> 1 > 1
false
iex> 1.1 > 1
true
Determine if an element is :greater
or :equal
to another.
Examples
iex> use Realm.Ord
...> at_least?(2, 1)
true
...> at_least?([1, 2, 3], [])
true
...> at_least?([1, 2, 3], [1])
true
...> at_least?([1, 2, 3], [4])
false
left ^^^ right
View SourceRealm.Arrow.t() ^^^ Realm.Arrow.t() :: Realm.Arrow.t()
Take two arguments (as a 2-tuple), and run one function on the left side (first element), and run a different function on the right side (second element).
┌------> f.(a) = x -------┐
| v
{a, b} {x, y}
| ^
└------> g.(b) = y -------┘
Examples
iex> arr = fn x -> x - 10 end ^^^ fn y -> y <> "!" end
...> arr.({42, "Hi"})
{32, "Hi!"}
iex> {42, "Hi"} |> (fn x -> x - 10 end ^^^ fn y -> y <> "!" end).()
{32, "Hi!"}
append(left, right)
View Sourceappend(Realm.Semigroup.t(), Realm.Semigroup.t()) :: Realm.Semigroupoid.t()
There is an operator alias a <> b
. Since this conflicts with Kernel.<>/2
,
use Realm,Semigroup
will automatically exclude the Kernel operator.
This is highly recommended, since <>
behaves the same on bitstrings, but is
now available on more datatypes.
Examples
iex> use Realm.Semigroup
...> 1 <> 2 <> 3 <> 5 <> 7
18
iex> use Realm.Semigroup
...> append([1, 2, 3], [4, 5, 6]) |> append([7, 8, 9])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
iex> use Realm.Semigroup
...> append("foo", " ") |> append("bar")
"foo bar"
at_least?(left, right)
View Sourceat_least?(Realm.Ord.t(), Realm.Ord.t()) :: boolean()
Determine if an element is :greater
or :equal
to another.
Examples
iex> use Realm.Ord
...> 2 >= 1
true
...> [1, 2, 3] >= []
true
...> [1, 2, 3] >= [1]
true
...> [1, 2, 3] >= [4]
false
at_most?(left, right)
View Sourceat_most?(Realm.Ord.t(), Realm.Ord.t()) :: boolean()
Determine if an element is :lesser
or :equal
to another.
Examples
iex> use Realm.Ord
...> at_most?(1, 2)
true
...> at_most?([], [1, 2, 3])
false
...> at_most?([1], [1, 2, 3])
true
...> at_most?([4], [1, 2, 3])
false
compose(g, f)
View Sourcecompose(Realm.Semigroupoid.t(), any()) :: Realm.Semigroupoid.t()
Composition operator "the math way". Alias for compose/2
.
Examples
iex> times_ten_plus_one = compose(fn x -> x + 1 end, fn y -> y * 10 end)
...>
...> times_ten_plus_one.(5)
51
equal?(left, right)
View Sourceequal?(Realm.Setoid.t(), Realm.Setoid.t()) :: boolean()
Determine if an element is equal to another.
Examples
iex> use Realm.Ord
...> equal?(2, 1)
false
...> equal?(1, 1)
true
fanout(f, g)
View Sourcefanout(Realm.Arrow.t(), Realm.Arrow.t()) :: Realm.Arrow.t()
Duplicate incoming data into both halves of a 2-tuple, and run one function on the left copy, and a different function on the right copy.
┌------> f.(a) = x ------┐
| v
a ---> split = {a, a} {x, y}
| ^
└------> g.(a) = y ------┘
Examples
iex> fanned = fn x -> x - 10 end &&& fn y -> inspect(y) <> "!" end
...> fanned.(42)
{32, "42!"}
iex> fanned =
...> fanout(fn x -> x - 10 end, fn y -> inspect(y) <> "!" end)
...> |> fanout(fn z -> inspect(z) <> "?" end)
...> |> fanout(fn d -> inspect(d) <> inspect(d) end)
...> |> fanout(fn e -> e / 2 end)
...>
...> fanned.(42)
{{{{32, "42!"}, "42?"}, "4242"}, 21.0}
flow_compose(f, g)
View Sourceflow_compose(Realm.Semigroupoid.t(), any()) :: Realm.Semigroupoid.t()
Composition operator "the pipe way". Alias for compose/2
.
Examples
iex> times_ten_plus_one = flow_compose(fn y -> y * 10 end, fn x -> x + 1 end)
...>
...> times_ten_plus_one.(5)
51
greater?(left, right)
View Sourcegreater?(Realm.Ord.t(), Realm.Ord.t()) :: boolean()
Determine if an element is :greater
than another.
Examples
iex> greater?(1, 1)
false
iex> greater?(1.1, 1)
true
lesser?(left, right)
View Sourcelesser?(Realm.Ord.t(), Realm.Ord.t()) :: boolean()
Determine if an element is :lesser
than another.
Examples
iex> lesser?(1, 1)
false
iex> lesser?(1, 1.1)
true
lift(functor, fun)
View Sourcelift(Realm.Functor.t(), (... -> any())) :: Realm.Functor.t()
map/2
but with the function automatically curried
Examples
iex> lift([1, 2, 3], fn x -> x + 55 end)
...> |> lift(fn y -> y * 10 end)
[560, 570, 580]
iex> lift([1, 2, 3], fn(x, y) -> x + y end)
...> |> List.first()
...> |> apply([9])
10
nonequivalent?(left, right)
View Sourcenonequivalent?(Realm.Setoid.t(), Realm.Setoid.t()) :: boolean()
The opposite of equivalent?/2
.
Examples
iex> nonequivalent?(1, 2)
true
over(fun, functor)
View Sourceover((... -> any()), Realm.Functor.t()) :: Realm.Functor.t()
lift/2
but with arguments flipped.
iex> lift(fn x -> x + 5 end, [1,2,3])
[6, 7, 8]
Note that the mnemonic is flipped from |>
, and combinging directions can
be confusing. It's generally recommended to use ~>
, or to keep <~
on
the same line both of it's arguments:
iex> over(fn(x, y) -> x + y end, [1, 2, 3])
...> |> List.first()
...> |> apply([9])
10
...or in an expression that's only pointing left:
iex> over(fn y -> y * 10 end, fn x -> x + 55 end)
...> |> over([1, 2, 3])
[560, 570, 580]
product(f, g)
View Sourceproduct(Realm.Arrow.t(), Realm.Arrow.t()) :: Realm.Arrow.t()
Take two arguments (as a 2-tuple), and run one function on the left side (first element), and run a different function on the right side (second element).
┌------> f.(a) = x -------┐
| v
{a, b} {x, y}
| ^
└------> g.(b) = y -------┘
Examples
iex> arr = product(fn x -> x - 10 end, fn y -> y <> "!" end)
...> arr.({42, "Hi"})
{32, "Hi!"}
iex> {42, "Hi"} |> product(fn x -> x - 10 end, fn y -> y <> "!" end).()
{32, "Hi!"}
provide(funs, apply)
View Sourceprovide(Realm.Apply.t(), Realm.Apply.t()) :: Realm.Apply.t()
Same as ap/2
, but with all functions curried.
Examples
iex> [fn x -> x + 1 end, fn y -> y * 10 end] <<~ [1, 2, 3]
[2, 3, 4, 10, 20, 30]
iex> import Realm.Functor
...>
...> [100, 200]
...> ~> fn(x, y, z) -> x * y / z end
...> |> provide([5, 2])
...> |> provide([100, 50])
...> |> provide(fn x -> x + 1 end)
[6.0, 11.0, 3.0, 5.0, 11.0, 21.0, 5.0, 9.0]
iex> import Realm.Functor, only: [<~: 2]
...> fn(a, b, c, d) -> a * b - c + d end <~ [1, 2] |> provide([3, 4]) |> provide([5, 6]) |> provide([7, 8])
[5, 6, 4, 5, 6, 7, 5, 6, 8, 9, 7, 8, 10, 11, 9, 10]
supply(apply, funs)
View Sourcesupply(Realm.Apply.t(), Realm.Apply.t()) :: Realm.Apply.t()
Same as convey/2
, but with all functions curried.
Examples
iex> [1, 2, 3] ~>> [fn x -> x + 1 end, fn y -> y * 10 end]
[2, 10, 3, 20, 4, 30]
iex> import Realm.Functor
...>
...> [100, 50]
...> |> supply([5, 2] # Note the bracket
...> |> supply([100, 200] # on both `Apply` lines
...> ~> fn(x, y, z) -> x * y / z end))
[5.0, 10.0, 2.0, 4.0, 10.0, 20.0, 4.0, 8.0]
functor ~> fun
View SourceRealm.Functor.t() ~> (... -> any()) :: Realm.Functor.t()
map/2
but with the function automatically curried
Examples
iex> [1, 2, 3]
...> ~> fn x -> x + 55 end
...> ~> fn y -> y * 10 end
[560, 570, 580]
iex> [1, 2, 3]
...> ~> fn(x, y) -> x + y end
...> |> List.first()
...> |> apply([9])
10
apply ~>> funs
View SourceRealm.Apply.t() ~>> Realm.Apply.t() :: Realm.Apply.t()
Same as convey/2
, but with all functions curried.
Examples
iex> [1, 2, 3] ~>> [fn x -> x + 1 end, fn y -> y * 10 end]
[2, 10, 3, 20, 4, 30]
iex> import Realm.Functor
...>
...> [100, 50]
...> ~>> ([5, 2] # Note the bracket
...> ~>> ([100, 200] # on both `Apply` lines
...> ~> fn(x, y, z) -> x * y / z end))
[5.0, 10.0, 2.0, 4.0, 10.0, 20.0, 4.0, 8.0]