Skip to content

Commit

Permalink
Spotchecks
Browse files Browse the repository at this point in the history
  • Loading branch information
expede committed Jan 12, 2016
1 parent 1efe02e commit c6fa1ac
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
14 changes: 13 additions & 1 deletion lib/witchcraft/applicative/function.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Witchcraft.Applicative.Function do

import Kernel, except: [apply: 2]

import Quark, only: [flip: 1]
import Quark, only: [id: 1, flip: 1, constant: 2]
import Quark.Curry, only: [curry: 1]

import Witchcraft.Applicative, only: [apply: 2]
Expand All @@ -31,4 +31,16 @@ defmodule Witchcraft.Applicative.Function do
@spec lift(any, (... -> any)) :: any
def lift([value], fun), do: value ~> curry(fun)
def lift([head|tail], fun), do: Enum.reduce(tail, lift([head], fun), &apply/2)

@doc ~S"""
Sequentially `apply`, and discard the second value of each pair.
"""
@spec seq_first([any]) :: any
def seq_first([a,b]), do: lift([a,b], &constant/2)

@doc ~S"""
Sequentially `apply`, and discard the first value of each pair.
"""
@spec seq_second([any]) :: any
def seq_second([a,b]), do: lift([a,b], fn x -> constant(x, &id/1) end)
end
45 changes: 24 additions & 21 deletions lib/witchcraft/applicative/property.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@ defmodule Witchcraft.Applicative.Property do
@spec spotcheck_identity(any) :: boolean
def spotcheck_identity(value), do: (value ~>> wrap(value, &id/1)) == value

# @doc ~S"""
# `apply` composes normally.
@doc ~S"""
`apply` composes normally.
iex> spotcheck_composition([1, 2], [&(&1 * 2)], [&(&1 * 10)])
true
# iex> spotcheck_composition([1, 2], [&(&1)], [&(&1 * 2)], [&(&1 * 10)])
# true
"""
@spec spotcheck_composition(any, any, any) :: boolean
def spotcheck_composition(value, fun1, fun2) do
wrap(value, &compose/2) <<~ fun1 <<~ fun2 <<~ value == fun1 <<~ (fun2 <<~ value)
end

# """
# # @spec
# def spotcheck_composition(x, u, v, w) do
# x ~>> (wrap(u, &compose/2) <<~ u <<~ v <<~ w) == x ~>> u ~>> (v ~>> w)
# end
@doc ~S"""
`apply`ing a `wrap`ped function to a `wrap`ped value is the same as wrapping the
result of the function on that value.
Expand All @@ -60,21 +61,23 @@ defmodule Witchcraft.Applicative.Property do
wrap(specemin, val) ~>> wrap(specemin, curried) == wrap(specemin, curried.(val))
end

# @doc ~S"""
# The order does not matter when `apply`ing to a `wrap`ped value
# and a `wrap`ped function.
@doc ~S"""
The order does not matter when `apply`ing to a `wrap`ped value
and a `wrap`ped function.
```elixir
# ```elixir
iex> spotcheck_interchange(1, [&(&1 * 10)])
true
# iex> spotcheck_interchange(1, [&(&1 * 10)])
# true
```
# ```
# """
# @spec spotcheck_interchange(any, any) :: boolean
# def spotcheck_interchange(bare_val, wrapped_fun) do
# wrap(wrapped_fun, bare_val) ~>> wrapped_fun == wrapped_fun ~>> wrap(wrapped_fun, &(bare_val |> &1))
# end
"""
@spec spotcheck_interchange(any, any) :: boolean
def spotcheck_interchange(bare_val, wrapped_fun) do
wrap(wrapped_fun, bare_val) ~>> wrapped_fun
== wrapped_fun ~>> wrap(wrapped_fun, &(bare_val |> curry(&1).()))
end

@doc ~S"""
Expand Down

0 comments on commit c6fa1ac

Please sign in to comment.