diff --git a/lib/type_class.ex b/lib/type_class.ex index d7466f9..4b445ef 100644 --- a/lib/type_class.ex +++ b/lib/type_class.ex @@ -154,6 +154,8 @@ defmodule TypeClass do TypeClass.run_where!() TypeClass.Dependency.run() + + # FIXME if check_time: :aot, :compile? TypeClass.Property.ensure!() end end @@ -230,6 +232,13 @@ defmodule TypeClass do # __MODULE__ == datatype datatype_module = unquote(datatype) + # FIXME if to run at test time + # defmodule unquote(datatype).Property do + # @moduledoc false + # + # unquote(body) + # end + defimpl unquote(class).Proto, for: datatype_module do import TypeClass.Property.Generator.Custom @@ -250,35 +259,36 @@ defmodule TypeClass do def __force_type_instance__, do: @force_type_instance end - cond do - unquote(class).__force_type_class__() -> - IO.warn(""" - The type class #{unquote(class)} has been forced to bypass \ - all property checks for all data types. This is very rarely valid, \ - as all type classes should have properties associted with them. - - For more, please see the TypeClass README: - https://github.com/expede/type_class/blob/master/README.md - """) - - instance.__force_type_instance__() -> - IO.warn(""" - The data type #{unquote(datatype)} has been forced to skip property \ - validation for the type class #{unquote(class)} - - This is sometimes valid, since TypeClass's property checker \ - may not be able to accurately validate all data types correctly for \ - all possible cases. Forcing a type instance in this way is like telling \ - the checker "trust me this is correct", and should only be used as \ - a last resort. - - For more, please see the TypeClass README: - https://github.com/expede/type_class/blob/master/README.md - """) - - true -> - unquote(datatype) |> conforms(to: unquote(class)) - end + # FIXME only if checked AOT + # cond do + # unquote(class).__force_type_class__() -> + # IO.warn(""" + # The type class #{unquote(class)} has been forced to bypass \ + # all property checks for all data types. This is very rarely valid, \ + # as all type classes should have properties associted with them. + + # For more, please see the TypeClass README: + # https://github.com/expede/type_class/blob/master/README.md + # """) + + # instance.__force_type_instance__() -> + # IO.warn(""" + # The data type #{unquote(datatype)} has been forced to skip property \ + # validation for the type class #{unquote(class)} + + # This is sometimes valid, since TypeClass's property checker \ + # may not be able to accurately validate all data types correctly for \ + # all possible cases. Forcing a type instance in this way is like telling \ + # the checker "trust me this is correct", and should only be used as \ + # a last resort. + + # For more, please see the TypeClass README: + # https://github.com/expede/type_class/blob/master/README.md + # """) + + # true -> + # unquote(datatype) |> conforms(to: unquote(class)) + # end end end @@ -506,15 +516,14 @@ 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` + # NOTE: only follows chain if dependency has a `where` if Exceptional.Safe.safe(&Protocol.assert_protocol!/1).(proto) == :ok do Protocol.assert_impl!(proto, unquote(datatype)) end end - for {prop_name, _one} <- unquote(class).Property.__info__(:functions) do - TypeClass.Property.run!(unquote(datatype), unquote(class), prop_name) - end + # FIXME only if at compile time + TypeClass.Property.check_all!(unquote(class), unquote(class)) # FIXME end end diff --git a/lib/type_class/property.ex b/lib/type_class/property.ex index bdd4a56..c9014c0 100644 --- a/lib/type_class/property.ex +++ b/lib/type_class/property.ex @@ -15,9 +15,9 @@ defmodule TypeClass.Property do end end - @doc "Run all properties for the type class" - @spec run!(module(), module(), atom(), non_neg_integer()) :: no_return() - def run!(datatype, class, prop_name, times \\ 100) do + @doc "Check all properties for the type class" + @spec check!(module(), module(), atom(), non_neg_integer()) :: no_return() + def check!(datatype, class, prop_name, times \\ 100) do property_module = Module.concat(class, Property) custom_generator = Module.concat([class, "Proto", datatype]).__custom_generator__() @@ -37,6 +37,13 @@ defmodule TypeClass.Property do |> Enum.take(times) end + # FIXME doc & typespec + def check_all!(datatype, class, times \\ 100) do + for {prop_name, _one} <- Module.concat(class, Property).__info__(:functions) do + TypeClass.Property.check!(datatype, class, prop_name, times) + end + end + @doc ~S""" Check for equality while handling special cases that normally don't equate in Elixir. For example, only check float accuracy to 5 decimal places due to internal rounding diff --git a/mix.exs b/mix.exs index f30b0f0..308c508 100644 --- a/mix.exs +++ b/mix.exs @@ -9,7 +9,7 @@ defmodule TypeClass.Mixfile do preferred_cli_env: [espec: :test], # Versions - version: "1.2.7", + version: "2.0.0-rc.1", elixir: "~> 1.11", # Docs @@ -35,8 +35,8 @@ defmodule TypeClass.Mixfile do [ {:exceptional, "~> 2.1"}, - {:espec, "~> 1.8", only: :test, runtime: false}, - {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, + {:espec, "~> 1.8", only: :test, runtime: false}, + {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, {:inch_ex, "~> 2.0", only: [:dev, :docs, :test], runtime: false}, {:dialyxir, "~> 1.1", only: :dev, runtime: false}, diff --git a/nix/sources.json b/nix/sources.json index 189720c..6f90240 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -5,10 +5,10 @@ "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e716ddfac4be879ffbae75c3914a538dd5d4d12e", - "sha256": "0c2090sz4nvd1bqa9bfz3b6mj0q8b7v4jzgsykn2hf291l3h94d6", + "rev": "ac60476ed94fd5424d9f3410c438825f793a8cbb", + "sha256": "1dlvpdsy5v09c7rj5f7xgakyj722yqr4415davjpcmrk4n5kw76v", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/e716ddfac4be879ffbae75c3914a538dd5d4d12e.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/ac60476ed94fd5424d9f3410c438825f793a8cbb.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "niv": { @@ -17,10 +17,10 @@ "homepage": "https://github.com/nmattia/niv", "owner": "nmattia", "repo": "niv", - "rev": "af958e8057f345ee1aca714c1247ef3ba1c15f5e", - "sha256": "1qjavxabbrsh73yck5dcq8jggvh3r2jkbr6b5nlz5d9yrqm9255n", + "rev": "94080ae8286024820c570a2a24ed7c36d7ad04a9", + "sha256": "0wlk52zwlrq727x3z1vg9d9qq4zw62ab5jzg4068iqb6hyb0cr0w", "type": "tarball", - "url": "https://github.com/nmattia/niv/archive/af958e8057f345ee1aca714c1247ef3ba1c15f5e.tar.gz", + "url": "https://github.com/nmattia/niv/archive/94080ae8286024820c570a2a24ed7c36d7ad04a9.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs": { @@ -29,10 +29,10 @@ "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "60b18a066e8ce5dd21ebff5324345d3586a67ad9", - "sha256": "1cr7r16vb4nxifykhak8awspdpr775kafrl7p6asgwicsng7giya", + "rev": "1f7155200fa1eb752054e2c9062bfdeb023e8098", + "sha256": "0l03az63aw649lyh037csiyarxgbwbmk49lk5n466nmv5glpgzl5", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/60b18a066e8ce5dd21ebff5324345d3586a67ad9.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/1f7155200fa1eb752054e2c9062bfdeb023e8098.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "unstable": { @@ -41,10 +41,10 @@ "homepage": null, "owner": "NixOS", "repo": "nixpkgs", - "rev": "c5147860e23ed75ce9d40298c66b416c00be1167", - "sha256": "104mw4rfbzyrfkxq468dlk38drrjx92dgyvkazgci67a6cx3n6nx", + "rev": "efee454783c5c14ae78687439077c1d3f0544d97", + "sha256": "1qk4g8rav2mkbd6y2zr1pi3pxs4rwlkpr8xk51m0p26khprxvjaf", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/c5147860e23ed75ce9d40298c66b416c00be1167.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/efee454783c5c14ae78687439077c1d3f0544d97.tar.gz", "url_template": "https://github.com///archive/.tar.gz" } } diff --git a/shell.nix b/shell.nix index f2d1d98..94f97dc 100644 --- a/shell.nix +++ b/shell.nix @@ -19,6 +19,7 @@ elixir = [ unstable.elixir + unstable.elixir_ls ]; platform = @@ -35,7 +36,7 @@ in pkgs.mkShell { - name = "Quark"; + name = "TypeClass"; nativeBuildInputs = builtins.concatLists [ deps.common deps.elixir