From cde1a64b76b0153622ae79d7b0455916089c22cf Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Mon, 2 Jan 2017 14:36:28 +0900 Subject: [PATCH] Bump to 1.0.0 --- docs/all.json | 2 +- lib/type_class.ex | 1 + mix.exs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/all.json b/docs/all.json index 421bdfe..c998b95 100644 --- a/docs/all.json +++ b/docs/all.json @@ -1 +1 @@ -{"shell":true,"revision":"e7984e4ff2ed264c155114046ecdf8d35a7f058a","objects":[{"type":null,"source":"lib/type_class.ex:2","object_type":"ModuleObject","moduledoc":"Helpers for defining (bootstrapped, semi-)principled type classes\n\nGenerates a few modules and several functions and aliases. There is no need\nto use these internals directly, as the top-level API will suffice for actual\nproductive use.\n\n## Example\n\n defclass Semigroup do\n use Operator\n\n where do\n @operator :<|>\n def concat(a, b)\n end\n\n properties do\n def associative(data) do\n a = generate(data)\n b = generate(data)\n c = generate(data)\n\n left = a |> Semigroup.concat(b) |> Semigroup.concat(c)\n right = Semigroup.concat(a, Semigroup.concat(b, c))\n\n left == right\n end\n end\n end\n\n definst Semigroup, for: List do\n def concat(a, b), do: a ++ b\n end\n\n defclass Monoid do\n extend Semigroup\n\n where do\n def empty(sample)\n end\n\n properties do\n def left_identity(data) do\n a = generate(data)\n Semigroup.concat(empty(a), a) == a\n end\n\n def right_identity(data) do\n a = generate(data)\n Semigroup.concat(a, empty(a)) == a\n end\n end\n end\n\n definst Monoid, for: List do\n def empty(_), do: []\n end\n\n\n## Internal Structure\n\nA `type_class` is composed of several parts:\n- Dependencies\n- Protocol\n- Properties\n\n\n### Dependencies\n\nDependencies are the other type classes that the type class being\ndefined extends. For instance, Monoid has a Semigroup dependency.\n\nIt only needs the immediate parents in\nthe chain, as those type classes will have performed all of the checks required\nfor their parents.\n\n\n### Protocol\n\n`defclass Foo` generates a `Foo.Proto` submodule that holds all of the functions\nto be implemented (it's a normal protocol). It's a very lightweight & straightforward,\nbut The `Protocol` should never need to be called explicitly.\n\nMacro: `where do`\nOptional\n\n\n### Properties\n\nBeing a (quasi-)principled type class also means having properties. Users must\ndefine _at least one_ property, plus _at least one_ sample data generator.\nThese will be run at compile time and refuse to compile if they don't pass.\n\nAll custom structs need to implement the `TypeClass.Property.Generator` protocol.\nThis is called automatically by the prop checker. Base types have been implemented\nby this library.\n\nPlease note that class functions are aliased to the last segment of their name.\nex. `Foo.Bar.MyClass.quux` is automatically usable as `MyClass.quux` in the `proprties` block\n\nMacro: `properties do`\nNon-optional\n\n","module":"Elixir.TypeClass","id":"TypeClass"},{"type":null,"source":"lib/type_class/dependency.ex:2","object_type":"ModuleObject","moduledoc":"Helpers for setting type class dependencies\n","module":"Elixir.TypeClass.Dependency","id":"TypeClass.Dependency"},{"type":null,"source":"lib/type_class/property.ex:2","object_type":"ModuleObject","moduledoc":"A *very* simple prop checker","module":"Elixir.TypeClass.Property","id":"TypeClass.Property"},{"type":"exception","source":"lib/type_class/property/failed_check_error.ex:2","object_type":"ModuleObject","moduledoc":"Information about a failed property check\n\n## Examples\n\n %TypeClass.Property.FailedCheckError{\n message: \"List does not conform to property CoolClass.associative\",\n datatype: List,\n property: :associative,\n class: CoolClass\n }\n\n","module":"Elixir.TypeClass.Property.FailedCheckError","id":"TypeClass.Property.FailedCheckError"},{"type":"protocol","source":"lib/type_class/property/generator.ex:2","object_type":"ModuleObject","moduledoc":"Data generator protocol for property checks. The more variation the better.\n","module":"Elixir.TypeClass.Property.Generator","id":"TypeClass.Property.Generator"},{"type":"exception","source":"lib/type_class/property/undefined_error.ex:2","object_type":"ModuleObject","moduledoc":"Warning if a type class is missing properties.\nProperties are required for all type classes.\n","module":"Elixir.TypeClass.Property.UndefinedError","id":"TypeClass.Property.UndefinedError"},{"type":null,"source":"lib/type_class/utility/attribute.ex:2","object_type":"ModuleObject","moduledoc":"Helpers to module attributes","module":"Elixir.TypeClass.Utility.Attribute","id":"TypeClass.Utility.Attribute"},{"type":null,"source":"lib/type_class/utility/module.ex:2","object_type":"ModuleObject","moduledoc":"Naming convention helpers to help follow TypeClass conventions","module":"Elixir.TypeClass.Utility.Module","id":"TypeClass.Utility.Module"},{"type":"defmacro","source":"lib/type_class.ex:282","signature":[["fun_head",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"defalias","module_id":"TypeClass","id":"defalias/2","doc":"Delegate to a local function","arity":2},{"type":"defmacro","source":"lib/type_class.ex:108","signature":[["class_name",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"defclass","module_id":"TypeClass","id":"defclass/2","doc":"Top-level wrapper for all type class modules. Used as a replacement for `defmodule`.\n\n## Examples\n\n defclass Semigroup do\n where do\n def concat(a, b)\n end\n\n properties do\n def associative(data) do\n a = generate(data)\n b = generate(data)\n c = generate(data)\n\n left = a |> Semigroup.concat(b) |> Semigroup.concat(c)\n right = Semigroup.concat(a, Semigroup.concat(b, c))\n\n left == right\n end\n end\n end\n\n","arity":2},{"type":"defmacro","source":"lib/type_class.ex:149","signature":[["class",[],null],["opts",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"definst","module_id":"TypeClass","id":"definst/3","doc":"Define an instance of the type class. The rough equivalent of `defimpl`.\n`defimpl` will check the properties at compile time, and prevent compilation\nif the datatype does not conform to the protocol.\n\n## Examples\n\n definst Semigroup, for: List do\n def concat(a, b), do: a ++ b\n end\n\n","arity":3},{"type":"defmacro","source":"lib/type_class.ex:233","signature":[["list",[],"Elixir"]],"object_type":"FunctionObject","name":"properties","module_id":"TypeClass","id":"properties/1","doc":"Define properties that any instance of the type class must satisfy.\nThey must by unary (takes a data seed), and return a boolean (true if passes).\n\n`generate` is automatically imported\n\n## Examples\n\n defclass Semigroup do\n # ...\n\n properties do\n def associative(data) do\n a = generate(data)\n b = generate(data)\n c = generate(data)\n\n left = a |> Semigroup.concat(b) |> Semigroup.concat(c)\n right = Semigroup.concat(a, Semigroup.concat(b, c))\n\n left == right\n end\n end\n end\n\n","arity":1},{"type":"defmacro","source":"lib/type_class.ex:178","signature":[["list",[],"Elixir"]],"object_type":"FunctionObject","name":"where","module_id":"TypeClass","id":"where/1","doc":"Describe functions to be instantiated. Creates an internal protocol.\n\n## Examples\n\n defclass Semigroup do\n where do\n def concat(a, b)\n end\n\n # ...\n end\n\n","arity":1},{"type":"defmacro","source":"lib/type_class/dependency.ex:24","signature":[["parent_class",[],null]],"object_type":"FunctionObject","name":"extend","module_id":"TypeClass.Dependency","id":"extend/1","doc":"Set a type class dependency.\nie: another type class that need to be `definst`ed before this one.\n\n## Examples\n\n defmodule Quux do\n extend Foo\n extend Bar\n extend Baz\n\n # ...\n end\n\n","arity":1},{"type":"defmacro","source":"lib/type_class/dependency.ex:47","signature":[["parent_class",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"extend","module_id":"TypeClass.Dependency","id":"extend/2","doc":null,"arity":2},{"type":"defmacro","source":"lib/type_class/dependency.ex:61","signature":[],"object_type":"FunctionObject","name":"run","module_id":"TypeClass.Dependency","id":"run/0","doc":"The opposite of `set_up/1`: collect dependencies","arity":0},{"type":"defmacro","source":"lib/type_class/dependency.ex:15","signature":[],"object_type":"FunctionObject","name":"set_up","module_id":"TypeClass.Dependency","id":"set_up/0","doc":"Set up the dependency collection from `extend`","arity":0},{"type":"defmacro","source":"lib/type_class/property.ex:6","signature":[],"object_type":"FunctionObject","name":"ensure!","module_id":"TypeClass.Property","id":"ensure!/0","doc":"Ensure that the type class has defined properties","arity":0},{"type":"def","source":"lib/type_class/property.ex:33","signature":[["left",[],null],["right",[],null]],"object_type":"FunctionObject","name":"equal?","module_id":"TypeClass.Property","id":"equal?/2","doc":"Check for equality while handling special cases that normally don't equate in Elixir.\nFor example, only check float accuracy to 5 decimal places due to internal rounding\nmismatches from applying functions in differing order. This isn't totally theoretically\naccurate, but is in line with the spirit of Floats.\n","arity":2},{"type":"def","source":"lib/type_class/property.ex:19","signature":[["datatype",[],null],["class",[],null],["prop_name",[],null],["\\\\",[],[["times",[],null],100]]],"object_type":"FunctionObject","name":"run!","module_id":"TypeClass.Property","id":"run!/4","doc":"Run all properties for the type class","arity":4},{"type":"def","source":"lib/type_class/property/failed_check_error.ex:23","signature":[["msg",[],null]],"object_type":"FunctionObject","name":"exception","module_id":"TypeClass.Property.FailedCheckError","id":"exception/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/failed_check_error.ex:23","signature":[["exception",[],null]],"object_type":"FunctionObject","name":"message","module_id":"TypeClass.Property.FailedCheckError","id":"message/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/failed_check_error.ex:25","signature":[["datatype",[],null],["class",[],null],["prop_name",[],null]],"object_type":"FunctionObject","name":"new","module_id":"TypeClass.Property.FailedCheckError","id":"new/3","doc":"Convenience constructor\n\n## Examples\n\n iex> TypeClass.Property.FailedCheckError.new(List, CoolClass, :associative)\n %TypeClass.Property.FailedCheckError{\n message: \"List does not conform to property CoolClass.associative\",\n datatype: List,\n property: :associative,\n class: CoolClass\n }\n\n","arity":3},{"type":"def","source":"lib/type_class/property/generator.ex:1","signature":[["atom",[],"Elixir"]],"object_type":"FunctionObject","name":"__protocol__","module_id":"TypeClass.Property.Generator","id":"__protocol__/1","doc":false,"arity":1},{"type":"def","source":"lib/type_class/property/generator.ex:8","signature":[["sample",[],null]],"object_type":"FunctionObject","name":"generate","module_id":"TypeClass.Property.Generator","id":"generate/1","doc":"Generate a random example of datatype.\n\n## Examples\n\n defimpl TypeClass.Property.Generator, for: Integer do\n def generate(_), do: :rand.uniform(1000) * Enum.random([1, 1, 1, -1])\n end\n\n defimpl TypeClass.Property.Generator, for: BitString do\n def generate(_) do\n Stream.unfold(\"\", &({&1, :rand.uniform(90)}))\n |> Stream.drop(1)\n |> Stream.take(:rand.uniform(4))\n |> Enum.to_list\n |> List.to_string\n end\n end\n\n","arity":1},{"type":"def","source":"lib/type_class/property/generator.ex:1","signature":[["data",[],null]],"object_type":"FunctionObject","name":"impl_for","module_id":"TypeClass.Property.Generator","id":"impl_for/1","doc":false,"arity":1},{"type":"def","source":"lib/type_class/property/generator.ex:1","signature":[["data",[],null]],"object_type":"FunctionObject","name":"impl_for!","module_id":"TypeClass.Property.Generator","id":"impl_for!/1","doc":false,"arity":1},{"type":"def","source":"lib/type_class/property/undefined_error.ex:9","signature":[["msg",[],null]],"object_type":"FunctionObject","name":"exception","module_id":"TypeClass.Property.UndefinedError","id":"exception/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/undefined_error.ex:9","signature":[["exception",[],null]],"object_type":"FunctionObject","name":"message","module_id":"TypeClass.Property.UndefinedError","id":"message/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/undefined_error.ex:11","signature":[["class",[],null]],"object_type":"FunctionObject","name":"new","module_id":"TypeClass.Property.UndefinedError","id":"new/1","doc":"Convenience constructor\n\n## Examples\n\n iex> TypeClass.Property.UndefinedError.new(CoolClass)\n %TypeClass.Property.UndefinedError{\n type_class: CoolClass,\n message: ~S\"\n CoolClass has not defined any properties, but they are required.\n\n See `TypeClass.properties/1` for more\n \"\n }\n\n","arity":1},{"type":"defmacro","source":"lib/type_class/utility/attribute.ex:20","signature":[["attribute",[],null]],"object_type":"FunctionObject","name":"get","module_id":"TypeClass.Utility.Attribute","id":"get/1","doc":"Retrieve the compile-time value stored at the specified attribute key","arity":1},{"type":"defmacro","source":"lib/type_class/utility/attribute.ex:4","signature":[["attribute",[],null],["\\\\",[],[["opts",[],null],[]]]],"object_type":"FunctionObject","name":"register","module_id":"TypeClass.Utility.Attribute","id":"register/2","doc":"Set up a compile time attribute key for getting and setting","arity":2},{"type":"defmacro","source":"lib/type_class/utility/attribute.ex:12","signature":[["value",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"set","module_id":"TypeClass.Utility.Attribute","id":"set/2","doc":"Set a compile-time module attribute","arity":2},{"type":"def","source":"lib/type_class/utility/module.ex:91","signature":[["parent_module",[],null],["submodule",[],null]],"object_type":"FunctionObject","name":"append","module_id":"TypeClass.Utility.Module","id":"append/2","doc":null,"arity":2},{"type":"def","source":"lib/type_class/utility/module.ex:69","signature":[["module",[],null]],"object_type":"FunctionObject","name":"get_functions","module_id":"TypeClass.Utility.Module","id":"get_functions/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/utility/module.ex:22","signature":[["base_module",[],null]],"object_type":"FunctionObject","name":"to_property","module_id":"TypeClass.Utility.Module","id":"to_property/1","doc":"Generate the module name for the protocol portion of the class.\nDoes not nest `Protocol`s.\n\n## Examples\n\n iex> to_property MyClass.Awesome\n MyClass.Awesome.Property\n\n iex> to_property MyClass.Awesome.Property\n MyClass.Awesome.Property\n\n","arity":1},{"type":"def","source":"lib/type_class/utility/module.ex:6","signature":[["base_module",[],null]],"object_type":"FunctionObject","name":"to_protocol","module_id":"TypeClass.Utility.Module","id":"to_protocol/1","doc":"Generate the module name for the protocol portion of the class.\nDoes not nest `Protocol`s.\n\n## Examples\n\n iex> to_protocol MyClass.Awesome\n MyClass.Awesome.Protocol\n\n iex> to_protocol MyClass.Awesome.Protocol\n MyClass.Awesome.Protocol\n\n","arity":1},{"type":"def","source":"lib/type_class/utility/module.ex:38","signature":[["base_module",[],null],["child_name",[],null]],"object_type":"FunctionObject","name":"to_submodule","module_id":"TypeClass.Utility.Module","id":"to_submodule/2","doc":"Generate a submodule name. If the module already ends in the\nrequested submodule, it will return the module name unchanged.\n\n## Examples\n\n iex> MyModule.Awesome |> to_submodule(Submodule)\n MyModule.Awesome.Submodule\n\n iex> MyModule.Awesome |> to_submodule(\"Submodule\")\n MyModule.Awesome.Submodule\n\n iex> MyModule.Awesome.Submodule |> to_submodule(Submodule)\n MyModule.Awesome.Submodule\n\n","arity":2}],"language":"elixir","git_repo_url":"https://github.com/expede/type_class.git","client_version":"0.5.5","client_name":"inch_ex","branch_name":"master","args":[]} \ No newline at end of file +{"shell":true,"revision":"5bf14dd5777a4d0ecfb55b6efba42ecaf917e5cc","objects":[{"type":null,"source":"lib/type_class.ex:2","object_type":"ModuleObject","moduledoc":"Helpers for defining (bootstrapped, semi-)principled type classes\n\nGenerates a few modules and several functions and aliases. There is no need\nto use these internals directly, as the top-level API will suffice for actual\nproductive use.\n\n## Example\n\n defclass Semigroup do\n use Operator\n\n where do\n @operator :<|>\n def concat(a, b)\n end\n\n properties do\n def associative(data) do\n a = generate(data)\n b = generate(data)\n c = generate(data)\n\n left = a |> Semigroup.concat(b) |> Semigroup.concat(c)\n right = Semigroup.concat(a, Semigroup.concat(b, c))\n\n left == right\n end\n end\n end\n\n definst Semigroup, for: List do\n def concat(a, b), do: a ++ b\n end\n\n defclass Monoid do\n extend Semigroup\n\n where do\n def empty(sample)\n end\n\n properties do\n def left_identity(data) do\n a = generate(data)\n Semigroup.concat(empty(a), a) == a\n end\n\n def right_identity(data) do\n a = generate(data)\n Semigroup.concat(a, empty(a)) == a\n end\n end\n end\n\n definst Monoid, for: List do\n def empty(_), do: []\n end\n\n\n## Internal Structure\n\nA `type_class` is composed of several parts:\n- Dependencies\n- Protocol\n- Properties\n\n\n### Dependencies\n\nDependencies are the other type classes that the type class being\ndefined extends. For instance, Monoid has a Semigroup dependency.\n\nIt only needs the immediate parents in\nthe chain, as those type classes will have performed all of the checks required\nfor their parents.\n\n\n### Protocol\n\n`defclass Foo` generates a `Foo.Proto` submodule that holds all of the functions\nto be implemented (it's a normal protocol). It's a very lightweight & straightforward,\nbut The `Protocol` should never need to be called explicitly.\n\nMacro: `where do`\nOptional\n\n\n### Properties\n\nBeing a (quasi-)principled type class also means having properties. Users must\ndefine _at least one_ property, plus _at least one_ sample data generator.\nThese will be run at compile time and refuse to compile if they don't pass.\n\nAll custom structs need to implement the `TypeClass.Property.Generator` protocol.\nThis is called automatically by the prop checker. Base types have been implemented\nby this library.\n\nPlease note that class functions are aliased to the last segment of their name.\nex. `Foo.Bar.MyClass.quux` is automatically usable as `MyClass.quux` in the `proprties` block\n\nMacro: `properties do`\nNon-optional\n\n","module":"Elixir.TypeClass","id":"TypeClass"},{"type":null,"source":"lib/type_class/dependency.ex:2","object_type":"ModuleObject","moduledoc":"Helpers for setting type class dependencies\n","module":"Elixir.TypeClass.Dependency","id":"TypeClass.Dependency"},{"type":null,"source":"lib/type_class/property.ex:2","object_type":"ModuleObject","moduledoc":"A *very* simple prop checker","module":"Elixir.TypeClass.Property","id":"TypeClass.Property"},{"type":"exception","source":"lib/type_class/property/failed_check_error.ex:2","object_type":"ModuleObject","moduledoc":"Information about a failed property check\n\n## Examples\n\n %TypeClass.Property.FailedCheckError{\n message: \"List does not conform to property CoolClass.associative\",\n datatype: List,\n property: :associative,\n class: CoolClass\n }\n\n","module":"Elixir.TypeClass.Property.FailedCheckError","id":"TypeClass.Property.FailedCheckError"},{"type":"protocol","source":"lib/type_class/property/generator.ex:2","object_type":"ModuleObject","moduledoc":"Data generator protocol for property checks. The more variation the better.\n","module":"Elixir.TypeClass.Property.Generator","id":"TypeClass.Property.Generator"},{"type":"exception","source":"lib/type_class/property/undefined_error.ex:2","object_type":"ModuleObject","moduledoc":"Warning if a type class is missing properties.\nProperties are required for all type classes.\n","module":"Elixir.TypeClass.Property.UndefinedError","id":"TypeClass.Property.UndefinedError"},{"type":null,"source":"lib/type_class/utility/attribute.ex:2","object_type":"ModuleObject","moduledoc":"Helpers to module attributes","module":"Elixir.TypeClass.Utility.Attribute","id":"TypeClass.Utility.Attribute"},{"type":null,"source":"lib/type_class/utility/module.ex:2","object_type":"ModuleObject","moduledoc":"Naming convention helpers to help follow TypeClass conventions","module":"Elixir.TypeClass.Utility.Module","id":"TypeClass.Utility.Module"},{"type":"defmacro","source":"lib/type_class.ex:304","signature":[["list",[],"Elixir"]],"object_type":"FunctionObject","name":"conforms","module_id":"TypeClass","id":"conforms/1","doc":"Variant of `conforms/2` that can be called within a data module","arity":1},{"type":"defmacro","source":"lib/type_class.ex:286","signature":[["datatype",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"conforms","module_id":"TypeClass","id":"conforms/2","doc":"Check that a datatype conforms to the class hierarchy and properties","arity":2},{"type":"defmacro","source":"lib/type_class.ex:279","signature":[["fun_head",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"defalias","module_id":"TypeClass","id":"defalias/2","doc":"Delegate to a local function","arity":2},{"type":"defmacro","source":"lib/type_class.ex:108","signature":[["class_name",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"defclass","module_id":"TypeClass","id":"defclass/2","doc":"Top-level wrapper for all type class modules. Used as a replacement for `defmodule`.\n\n## Examples\n\n defclass Semigroup do\n where do\n def concat(a, b)\n end\n\n properties do\n def associative(data) do\n a = generate(data)\n b = generate(data)\n c = generate(data)\n\n left = a |> Semigroup.concat(b) |> Semigroup.concat(c)\n right = Semigroup.concat(a, Semigroup.concat(b, c))\n\n left == right\n end\n end\n end\n\n","arity":2},{"type":"defmacro","source":"lib/type_class.ex:170","signature":[["class",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"definst","module_id":"TypeClass","id":"definst/2","doc":"Variant of `definst/2` for use inside of a `defstruct` module definition","arity":2},{"type":"defmacro","source":"lib/type_class.ex:149","signature":[["class",[],null],["opts",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"definst","module_id":"TypeClass","id":"definst/3","doc":"Define an instance of the type class. The rough equivalent of `defimpl`.\n`defimpl` will check the properties at compile time, and prevent compilation\nif the datatype does not conform to the protocol.\n\n## Examples\n\n definst Semigroup, for: List do\n def concat(a, b), do: a ++ b\n end\n\n","arity":3},{"type":"defmacro","source":"lib/type_class.ex:230","signature":[["list",[],"Elixir"]],"object_type":"FunctionObject","name":"properties","module_id":"TypeClass","id":"properties/1","doc":"Define properties that any instance of the type class must satisfy.\nThey must by unary (takes a data seed), and return a boolean (true if passes).\n\n`generate` is automatically imported\n\n## Examples\n\n defclass Semigroup do\n # ...\n\n properties do\n def associative(data) do\n a = generate(data)\n b = generate(data)\n c = generate(data)\n\n left = a |> Semigroup.concat(b) |> Semigroup.concat(c)\n right = Semigroup.concat(a, Semigroup.concat(b, c))\n\n left == right\n end\n end\n end\n\n","arity":1},{"type":"defmacro","source":"lib/type_class.ex:175","signature":[["list",[],"Elixir"]],"object_type":"FunctionObject","name":"where","module_id":"TypeClass","id":"where/1","doc":"Describe functions to be instantiated. Creates an internal protocol.\n\n## Examples\n\n defclass Semigroup do\n where do\n def concat(a, b)\n end\n\n # ...\n end\n\n","arity":1},{"type":"defmacro","source":"lib/type_class/dependency.ex:24","signature":[["parent_class",[],null]],"object_type":"FunctionObject","name":"extend","module_id":"TypeClass.Dependency","id":"extend/1","doc":"Set a type class dependency.\nie: another type class that need to be `definst`ed before this one.\n\n## Examples\n\n defmodule Quux do\n extend Foo\n extend Bar\n extend Baz\n\n # ...\n end\n\n","arity":1},{"type":"defmacro","source":"lib/type_class/dependency.ex:47","signature":[["parent_class",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"extend","module_id":"TypeClass.Dependency","id":"extend/2","doc":null,"arity":2},{"type":"defmacro","source":"lib/type_class/dependency.ex:61","signature":[],"object_type":"FunctionObject","name":"run","module_id":"TypeClass.Dependency","id":"run/0","doc":"The opposite of `set_up/1`: collect dependencies","arity":0},{"type":"defmacro","source":"lib/type_class/dependency.ex:15","signature":[],"object_type":"FunctionObject","name":"set_up","module_id":"TypeClass.Dependency","id":"set_up/0","doc":"Set up the dependency collection from `extend`","arity":0},{"type":"defmacro","source":"lib/type_class/property.ex:6","signature":[],"object_type":"FunctionObject","name":"ensure!","module_id":"TypeClass.Property","id":"ensure!/0","doc":"Ensure that the type class has defined properties","arity":0},{"type":"def","source":"lib/type_class/property.ex:33","signature":[["left",[],null],["right",[],null]],"object_type":"FunctionObject","name":"equal?","module_id":"TypeClass.Property","id":"equal?/2","doc":"Check for equality while handling special cases that normally don't equate in Elixir.\nFor example, only check float accuracy to 5 decimal places due to internal rounding\nmismatches from applying functions in differing order. This isn't totally theoretically\naccurate, but is in line with the spirit of Floats.\n","arity":2},{"type":"def","source":"lib/type_class/property.ex:19","signature":[["datatype",[],null],["class",[],null],["prop_name",[],null],["\\\\",[],[["times",[],null],100]]],"object_type":"FunctionObject","name":"run!","module_id":"TypeClass.Property","id":"run!/4","doc":"Run all properties for the type class","arity":4},{"type":"def","source":"lib/type_class/property/failed_check_error.ex:23","signature":[["msg",[],null]],"object_type":"FunctionObject","name":"exception","module_id":"TypeClass.Property.FailedCheckError","id":"exception/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/failed_check_error.ex:23","signature":[["exception",[],null]],"object_type":"FunctionObject","name":"message","module_id":"TypeClass.Property.FailedCheckError","id":"message/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/failed_check_error.ex:25","signature":[["datatype",[],null],["class",[],null],["prop_name",[],null]],"object_type":"FunctionObject","name":"new","module_id":"TypeClass.Property.FailedCheckError","id":"new/3","doc":"Convenience constructor\n\n## Examples\n\n iex> TypeClass.Property.FailedCheckError.new(List, CoolClass, :associative)\n %TypeClass.Property.FailedCheckError{\n message: \"List does not conform to property CoolClass.associative\",\n datatype: List,\n property: :associative,\n class: CoolClass\n }\n\n","arity":3},{"type":"def","source":"lib/type_class/property/generator.ex:1","signature":[["atom",[],"Elixir"]],"object_type":"FunctionObject","name":"__protocol__","module_id":"TypeClass.Property.Generator","id":"__protocol__/1","doc":false,"arity":1},{"type":"def","source":"lib/type_class/property/generator.ex:8","signature":[["sample",[],null]],"object_type":"FunctionObject","name":"generate","module_id":"TypeClass.Property.Generator","id":"generate/1","doc":"Generate a random example of datatype.\n\n## Examples\n\n defimpl TypeClass.Property.Generator, for: Integer do\n def generate(_), do: :rand.uniform(1000) * Enum.random([1, 1, 1, -1])\n end\n\n defimpl TypeClass.Property.Generator, for: BitString do\n def generate(_) do\n Stream.unfold(\"\", &({&1, :rand.uniform(90)}))\n |> Stream.drop(1)\n |> Stream.take(:rand.uniform(4))\n |> Enum.to_list\n |> List.to_string\n end\n end\n\n","arity":1},{"type":"def","source":"lib/type_class/property/generator.ex:1","signature":[["data",[],null]],"object_type":"FunctionObject","name":"impl_for","module_id":"TypeClass.Property.Generator","id":"impl_for/1","doc":false,"arity":1},{"type":"def","source":"lib/type_class/property/generator.ex:1","signature":[["data",[],null]],"object_type":"FunctionObject","name":"impl_for!","module_id":"TypeClass.Property.Generator","id":"impl_for!/1","doc":false,"arity":1},{"type":"def","source":"lib/type_class/property/undefined_error.ex:9","signature":[["msg",[],null]],"object_type":"FunctionObject","name":"exception","module_id":"TypeClass.Property.UndefinedError","id":"exception/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/undefined_error.ex:9","signature":[["exception",[],null]],"object_type":"FunctionObject","name":"message","module_id":"TypeClass.Property.UndefinedError","id":"message/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/property/undefined_error.ex:11","signature":[["class",[],null]],"object_type":"FunctionObject","name":"new","module_id":"TypeClass.Property.UndefinedError","id":"new/1","doc":"Convenience constructor\n\n## Examples\n\n iex> TypeClass.Property.UndefinedError.new(CoolClass)\n %TypeClass.Property.UndefinedError{\n type_class: CoolClass,\n message: ~S\"\n CoolClass has not defined any properties, but they are required.\n\n See `TypeClass.properties/1` for more\n \"\n }\n\n","arity":1},{"type":"defmacro","source":"lib/type_class/utility/attribute.ex:20","signature":[["attribute",[],null]],"object_type":"FunctionObject","name":"get","module_id":"TypeClass.Utility.Attribute","id":"get/1","doc":"Retrieve the compile-time value stored at the specified attribute key","arity":1},{"type":"defmacro","source":"lib/type_class/utility/attribute.ex:4","signature":[["attribute",[],null],["\\\\",[],[["opts",[],null],[]]]],"object_type":"FunctionObject","name":"register","module_id":"TypeClass.Utility.Attribute","id":"register/2","doc":"Set up a compile time attribute key for getting and setting","arity":2},{"type":"defmacro","source":"lib/type_class/utility/attribute.ex:12","signature":[["value",[],null],["list",[],"Elixir"]],"object_type":"FunctionObject","name":"set","module_id":"TypeClass.Utility.Attribute","id":"set/2","doc":"Set a compile-time module attribute","arity":2},{"type":"def","source":"lib/type_class/utility/module.ex:91","signature":[["parent_module",[],null],["submodule",[],null]],"object_type":"FunctionObject","name":"append","module_id":"TypeClass.Utility.Module","id":"append/2","doc":null,"arity":2},{"type":"def","source":"lib/type_class/utility/module.ex:69","signature":[["module",[],null]],"object_type":"FunctionObject","name":"get_functions","module_id":"TypeClass.Utility.Module","id":"get_functions/1","doc":null,"arity":1},{"type":"def","source":"lib/type_class/utility/module.ex:22","signature":[["base_module",[],null]],"object_type":"FunctionObject","name":"to_property","module_id":"TypeClass.Utility.Module","id":"to_property/1","doc":"Generate the module name for the protocol portion of the class.\nDoes not nest `Protocol`s.\n\n## Examples\n\n iex> to_property MyClass.Awesome\n MyClass.Awesome.Property\n\n iex> to_property MyClass.Awesome.Property\n MyClass.Awesome.Property\n\n","arity":1},{"type":"def","source":"lib/type_class/utility/module.ex:6","signature":[["base_module",[],null]],"object_type":"FunctionObject","name":"to_protocol","module_id":"TypeClass.Utility.Module","id":"to_protocol/1","doc":"Generate the module name for the protocol portion of the class.\nDoes not nest `Protocol`s.\n\n## Examples\n\n iex> to_protocol MyClass.Awesome\n MyClass.Awesome.Protocol\n\n iex> to_protocol MyClass.Awesome.Protocol\n MyClass.Awesome.Protocol\n\n","arity":1},{"type":"def","source":"lib/type_class/utility/module.ex:38","signature":[["base_module",[],null],["child_name",[],null]],"object_type":"FunctionObject","name":"to_submodule","module_id":"TypeClass.Utility.Module","id":"to_submodule/2","doc":"Generate a submodule name. If the module already ends in the\nrequested submodule, it will return the module name unchanged.\n\n## Examples\n\n iex> MyModule.Awesome |> to_submodule(Submodule)\n MyModule.Awesome.Submodule\n\n iex> MyModule.Awesome |> to_submodule(\"Submodule\")\n MyModule.Awesome.Submodule\n\n iex> MyModule.Awesome.Submodule |> to_submodule(Submodule)\n MyModule.Awesome.Submodule\n\n","arity":2}],"language":"elixir","git_repo_url":"https://github.com/expede/type_class.git","client_version":"0.5.5","client_name":"inch_ex","branch_name":"master","args":[]} \ No newline at end of file diff --git a/lib/type_class.ex b/lib/type_class.ex index 1442a14..33badb4 100644 --- a/lib/type_class.ex +++ b/lib/type_class.ex @@ -289,6 +289,7 @@ defmodule TypeClass do for dependency <- unquote(class).__dependencies__ do proto = Module.concat(Module.split(dependency) ++ ["Proto"]) + # NOTE: does not follow chain if dependency has no `where` if Exceptional.Safe.safe(&Protocol.assert_protocol!/1).(proto) == :ok do Protocol.assert_impl!(proto, unquote datatype) end diff --git a/mix.exs b/mix.exs index 0a76589..e7295c2 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,7 @@ defmodule TypeClass.Mixfile do name: "TypeClass", description: "(Semi-)principled type classes for Elixir", - version: "1.0.0-alpha7", + version: "1.0.0", elixir: "~> 1.3", package: [ @@ -19,7 +19,7 @@ defmodule TypeClass.Mixfile do source_url: "https://github.com/expede/type_class", homepage_url: "https://github.com/expede/type_class", - aliases: ["quality": ["espec", "credo --strict", "inch"]], + aliases: ["quality": ["credo --strict", "inch"]], preferred_cli_env: [espec: :test],