View Source Witchcraft.Functor (Witchcraft v1.0.6-doma)

Functors are datatypes that allow the application of functions to their interior values. Always returns data in the same structure (same size, tree layout, and so on).

Please note that bitstrings are not functors, as they fail the functor composition constraint. They change the structure of the underlying data, and thus composed lifting does not equal lifing a composed function. If you need to map over a bitstring, convert it to and from a charlist.

type-class

Type Class

An instance of Witchcraft.Functor must define Witchcraft.Functor.map/2.

Functor  [map/2]

Link to this section Summary

Functions

~>/2 with arguments flipped.

map with its arguments flipped.

async_map/2 with arguments flipped.

The same as async_map/2, except with the mapping function curried

map a function over a data structure, with each mapping occuring asynchronously.

async_lift/2 with arguments flipped.

map/2 but with the function automatically curried

map a function into one layer of a data wrapper. There is an autocurrying variant: lift/2.

lift/2 but with arguments flipped.

Replace all inner elements with a constant value

Operator alias for lift/2

Link to this section Types

Link to this section Functions

~>/2 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]
@spec across((any() -> any()), t()) :: t()

map with its arguments flipped.

examples

Examples

iex> across(fn x -> x + 1 end, [1, 2, 3])
[2, 3, 4]

iex> fn
...>   int when is_integer(int) -> int * 100
...>   value -> inspect(value)
...> end
...> |> across(%{a: 2, b: [1, 2, 3]})
%{a: 200, b: "[1, 2, 3]"}
Link to this function

async_across(fun, functor)

View Source
@spec async_across((any() -> any()), t()) :: t()

async_map/2 with arguments flipped.

examples

Examples

iex> fn x -> x * 10 end
...> |> async_across([1, 2, 3])
[10, 20, 30]

fn x ->
  Process.sleep(500)
  x * 10
end
|> async_across(Enumto_list(0..10_000))
#=> [0, 10, ...] in around a second
Link to this function

async_lift(functor, fun)

View Source
@spec async_lift(t(), (... -> any())) :: t()

The same as async_map/2, except with the mapping function curried

examples

Examples

iex> async_lift([1, 2, 3], fn x -> x * 10 end)
[10, 20, 30]

0..10_000
|> Enum.to_list()
|> async_lift(fn x ->
  Process.sleep(500)
  x * 10
end)
#=> [0, 10, ...] in around a second
@spec async_map(t(), (any() -> any())) :: t()

map a function over a data structure, with each mapping occuring asynchronously.

Especially helpful when each application take a long time.

examples

Examples

iex> async_map([1, 2, 3], fn x -> x * 10 end)
[10, 20, 30]

0..10_000
|> Enum.to_list()
|> async_map(fn x ->
  Process.sleep(500)
  x * 10
end)
#=> [0, 10, ...] in around a second
Link to this function

async_over(fun, functor)

View Source
@spec async_over((... -> any()), t()) :: t()

async_lift/2 with arguments flipped.

examples

Examples

iex> fn x -> x * 10 end
...> |> async_over([1, 2, 3])
[10, 20, 30]

fn x ->
  Process.sleep(500)
  x * 10
end
|> async_over(Enumto_list(0..10_000))
#=> [0, 10, ...] in around a second
@spec lift(t(), (... -> any())) :: t()

map/2 but with the function automatically curried

examples

Examples

iex> lift([1, 2, 3], fn x -> x + 1 end)
[2, 3, 4]

iex> [1, 2, 3]
...> |> lift(fn x -> x + 55 end)
...> |> lift(fn y -> y * 10 end)
[560, 570, 580]

iex> [1, 2, 3]
...> |> lift(fn(x, y) -> x + y end)
...> |> List.first()
...> |> apply([9])
10
@spec map(t(), (any() -> any())) :: t()

map a function into one layer of a data wrapper. There is an autocurrying variant: lift/2.

examples

Examples

iex> map([1, 2, 3], fn x -> x + 1 end)
[2, 3, 4]

iex> %{a: 1, b: 2} ~> fn x -> x * 10 end
%{a: 10, b: 20}

iex> map(%{a: 2, b: [1, 2, 3]}, fn
...>   int when is_integer(int) -> int * 100
...>   value -> inspect(value)
...> end)
%{a: 200, b: "[1, 2, 3]"}
@spec over((... -> any()), t()) :: t()

lift/2 but with arguments flipped.

examples

Examples

iex> fn x -> x + 1 end |> over([1, 2, 3])
[2, 3, 4]
Link to this function

replace(wrapped, replace_with)

View Source
@spec replace(t(), any()) :: t()

Replace all inner elements with a constant value

examples

Examples

iex> replace([1, 2, 3], "hi")
["hi", "hi", "hi"]

Operator alias for lift/2

example

Example

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