Giter Club home page Giter Club logo

type_class's People

Contributors

alfert avatar emoragaf avatar expede avatar futpib avatar icidasset avatar jechol avatar ktec avatar progsmile avatar qqwy avatar quinnwilton avatar toraritte avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

type_class's Issues

Q: How to work with functional values

I am implementing a Witchcraft.Functor, having an unary function as data inside a struct:

defclass Generator extends Witchcraft.Functor
where do
    @type gen_fun_t :: (non_neg_integer -> any)
    defdata do
      gen_fun :: gen_fun_t() 
    end
end

The Functor's map function is implemented as

def map(gen, map_fun) do
  fun seed ->
        gen.gen_fun.(seed)
        |> map_fun.()
   end
   |> Generator.new()
end

The property testing of Functor fails because the struct is compared and the functional values are different by definition of Erlang/Elixir (which is the reason why equals implements specific comparison method).

Is this the case for @force_type_instance true, is this a bug of equals (where it could be useful to define a equal function the type class instance) or am I missing an alternative approach?

Espec Tests: Proto.wrap/2 undefined

I ran the espec test on my setup (elixir 1.11), and, mostly as a way to slowly understand the code, I would like to address one of the warnings I got:

warning: Proto.wrap/2 is undefined (module Proto is not available or is yet to be defined)
  spec/type_class_spec.exs:194: TypeClassSpec.Applicative.wrap/2

This refers to this line.

I was wondering what is this supposed to refer to ? Is there something missing, or is this supposed to be an alias for Applicative.Proto.of/1 and the defdelegate arguments should be fixed ?

Thanks for the hint.

Clarification regarding generators

Oddly enough, both generators in the documentations and the generator I've seen in Maybe are ignoring their argument and use Enum.random().

This seems to be an anti-pattern in property-based testing because it relies on reproducibility of a random test that caught an error.

I assume that the underlying plumbing somehow sets a global seed for Enum.random(), perhaps mix test even does it itself (hence "Randomized with seed NNN" messages at the end of the tests), but in my opinion a clarification is required here.

Espec tests: TypeClassSpec.MoreProps.Proto is not a behaviour

I ran the espec test on my setup (elixir 1.11), and, mostly as a way to slowly understand the code, I would like to address one of the warnings I got:

warning: module TypeClassSpec.MoreProps.Proto is not a behaviour (in module TypeClassSpec.MoreProps.Proto.Integer)
  spec/type_class_spec.exs:82: TypeClassSpec.MoreProps.Proto.Integer (module)

This refers to this line. I also have this warning quite a few times when building witchcraft.

The Adder class doesn't trigger this warning, so it seems to be because there is no where section in the definition of MoreProps class... or because extend is not working as expected ? I'm guessing it should declare the protocol for this class, from the where section of the extended module somehow ?

Thanks for any info about this.

Property tests during compilation are getting in the way...

Hi everyone, here is some feedback...

After using type_class for a while, I reached the conclusion that running property tests during compilation doesn't match the "usual elixir developer" expectations. Well, at least mine, I'll let everyone else make their own mind about it while I attempt to make my case.

I see mainly two reasons:

  • False positives: if mix compile succeed, it might just be because the values generated didn't break the property, but the property may still be unsatisfied for values that weren't generated. Further mix test runs will not trigger the property tests again, and therefore will not expose the problem. We now have "broken code" compiled and tests passing...

  • Breaking the usual code / test cycle: the developer is writing tests & modifying code & writing tests while running mix test very frequently to see what tests are impacted by the code changes. I see this situation being more common with dynamic languages, where "exploratory coding" is easier, compared to compiled languages, where compile time make that somewhat less fluid...
    In this usecase, a developer can modify code and then running mix test will recompile, and maybe break on compilation (property test failed). Where is the code triggering the problem ? The property might be very remotely related with the changed code, and tracking it down maybe difficult, because now the developer cannot run tests anymore, until the cause for the property failing is found... Usually having multiple tests failing will indicate the code path that was affected by a change, but by running type_class property tests on their own, in the compilation phase, it has become impossible to run any other test to help track down the problem.

What does everyone else think ?

Overall I find type_class very useful for structuring code, but I would prefer typeclass property tests to run with mix test.
Especially because a codepath can jump through various protocol implementation in various files, having tests failing along the path would help... Maybe via a classtest macro, accepting the typeclass atom to test as parameter, that could be used with ExUnit just like doctest ?

`equal?` as protocol to implement ?

I recently had an issue where floats where embedded into a struct, and checking with equal? on the whole struct didn't round the float (as it does on one float).
I also don't want to have a property defined in a typeclass, with a specific notion of equality that depends on the implementation...

I am thinking that equal? should be defined in a protocol, and implementable for any struct, just like generator is ?
What do you all think ?

use TypeClass is superfluous

TypeClass.__using__/1 is defined as:

  defmacro __using__(_) do
    quote do
      require unquote(__MODULE__)
      import  unquote(__MODULE__)
    end
  end

When a module is imported, the imported macros can be invoked without require, so the require is not necessary. This leaves import as the sole member of __using__, which is considered a bad practice. It's much clearer to the user of the library to say what is happening when they see:

import TypeClass

than, when they see:

use TypeClass

That could be doing anything.

custom generator getting all kind of datatypes

This is an error similar to what I encountered while trying to implement a linearspace typeclass on top of Witchcraft.Monoid.

Here is a minimal example to reproduce the issue:

# -- type_class_check.ex --
#
# HOW TO USE:
# From iex, enter these lines (minus the prompt)
# 
# iex> Mix.install([ {:witchcraft, "~> 1.0"}, {:type_class, "~> 1.2"} ])
# :ok
# iex> c "type_class_check.ex"

import TypeClass

defclass SomeClass do
  extend Witchcraft.Monoid

  alias Witchcraft.Semigroup

  where do
    def merge(arg1, arg2)
  end

  properties do
    def commutativity(data) do
      a = generate(data)
      b = generate(data)
      Semigroup.append(a, b) == Semigroup.append(b, a)
    end
  end
end

definst SomeClass, for: Integer do
  # custom_generator(data) do
  #   data |> IO.inspect()
  # end

  def merge(arg1, arg2) do
    arg1 * arg2
  end
end

This should compile without problem, as expected.

However uncommenting the custom generator will reveal all the different sort of data that is passed to it. It doesn't match the current implementation (Integer) as I would have expected...


&:erlang.is_number/1
%{
  -262 => %{-239 => <<23, 44, 40, 86, 8, 28, 19, 9, 23, 51, 52, 15>>},
  618 => -1.0225806451612902,
  "\eSJ)A,>PS" => 3.297872340425532,
  <<82, 23, 77, 79, 72, 26, 88, 5, 46, 33, 8, 6, 79, 14, 68, 23, 74, 81, 31, 6>> => "6"
}

== Compilation error in file type_class_check.ex ==
** (FunctionClauseError) no function clause matching in Witchcraft.Semigroup.Proto.Function.append/2    
    
    The following arguments were given to Witchcraft.Semigroup.Proto.Function.append/2:
    
        # 1
        &:erlang.is_number/1
    
        # 2
        %{-262 => %{-239 => <<23, 44, 40, 86, 8, 28, 19, 9, 23, 51, 52, 15>>}, 618 => -1.0225806451612902, "\eSJ)A,>PS" => 3.297872340425532, <<82, 23, 77, 79, 72, 26, 88, 5, 46, 33, 8, 6, 79, 14, 68, 23, 74, 81, 31, 6>> => "6"}
    
    Attempted function clauses (showing 1 out of 1):
    
        def append(f, g) when is_function(g)
    
    (witchcraft 1.0.4) lib/witchcraft/semigroup.ex:120: Witchcraft.Semigroup.Proto.Function.append/2
    type_class_check.ex:23: SomeClass.Property.commutativity/1
    (type_class 1.2.8) lib/type_class/property.ex:32: anonymous fn/5 in TypeClass.Property.run!/4
    (elixir 1.14.3) lib/stream.ex:1557: Stream.do_repeatedly/3
    (elixir 1.14.3) lib/enum.ex:3448: Enum.take/2
    type_class_check.ex:37: anonymous fn/2 in :elixir_compiler_6.__FILE__/1
    (elixir 1.14.3) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
    type_class_check.ex:37: (file)
** (CompileError)  compile error
    (iex 1.14.3) lib/iex/helpers.ex:204: IEx.Helpers.c/2
    iex:3: (file)

I was actually trying this as a simple workaround for #19 ...

Now I am guessing the error is related to this package and the design of custom_generator, but I am not used to type_class, so feel free to let me know if I am just holding this wrong, or if I should post this somewhere else (witchcraft itself ?).

Cheers !

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.