Ah, that I'm not sure of. There is no run-time reflection in Haskell, though I don't doubt that artifacts of frightful intelligence exist to do what you ask. Hoogle is a good place to start for that sort of thing.
Though methodswith is of limited use for determine a minimal implementation. For instance, in my example, I can avoid implementing abs because I define flipsign. When defining an encoded floating point, tan magically works, but atan doesn't. *Sebastian Good* On Fri, Nov 21, 2014 at 2:47 PM, Mauro <mauro...@runbox.com> wrote: > Yep, defining == is needed to implement Eq. But then is there a way to > query what functions are constrained by Eq? For instance, give me a > list of all functions which Eq provides, i.e. with type: Eq(a) => ... > > This would be similar to methodswith in Julia, although methodswith > returns both the "implementation" functions as well as the "provided" > functions. Anyway, I was just wondering. > > On Fri, 2014-11-21 at 20:21, Sebastian Good < > sebast...@palladiumconsulting.com> wrote: > > I'm not sure I understand the distinction you make. You declare a > typeclass > > by defining the functions needed to qualify for it, as well as default > > implementations. e.g. > > > > class Eq a where > > (==), (/=) :: a -> a -> Bool > > x /= y = not (x == y) > > > > the typeclass 'Eq a' requires implementation of two functions, (==) and > > (/=), of type a -> a -> Bool, which would look like (a,a) --> Bool in the > > proposed Julia function type syntax). The (/=) function has a default > > implementation in terms of the (==) function, though you could define > your > > own for your own type if it were an instance of this typeclass. > > > > > > *Sebastian Good* > > > > > > On Fri, Nov 21, 2014 at 2:11 PM, Mauro <mauro...@runbox.com> wrote: > > > >> Sebastian, in Haskell, is there a way to get all functions which are > >> constrained by one or several type classes? I.e. which functions are > >> provided by a type-class? (as opposed to which functions need to be > >> implemented to belong to a type-class) > >> > >> On Fri, 2014-11-21 at 16:54, Jiahao Chen <jia...@mit.edu> wrote: > >> >> If instead I want to say "this new type acts like an Integer", > there's > >> no > >> > canonical place for me to find out what all the functions are I need > to > >> > implement. > >> > > >> > The closest thing we have now is methodswith(Integer) > >> > and methodswith(Integer, true) (the latter gives also all the methods > >> that > >> > Integer inherits from its supertypes). > >> > > >> > Thanks, > >> > > >> > Jiahao Chen > >> > Staff Research Scientist > >> > MIT Computer Science and Artificial Intelligence Laboratory > >> > > >> > On Fri, Nov 21, 2014 at 9:54 AM, Sebastian Good < > >> > sebast...@palladiumconsulting.com> wrote: > >> > > >> >> I will look into Traits.jl -- interesting package. > >> >> > >> >> To get traction and some of the great power of comparability, the > base > >> >> library will need to be carefully decomposed into traits, which (as > >> noted > >> >> in some of the issue conversations on github) takes you straight to > the > >> >> great research Haskell is doing in this area. > >> >> > >> >> *Sebastian Good* > >> >> > >> >> > >> >> On Fri, Nov 21, 2014 at 9:38 AM, John Myles White < > >> >> johnmyleswh...@gmail.com> wrote: > >> >> > >> >>> This sounds a bit like a mix of two problems: > >> >>> > >> >>> (1) A lack of interfaces: > >> >>> > >> >>> - a) A lack of formal interfaces, which will hopefully be > addressed by > >> >>> something like Traits.jl at some point. ( > >> >>> https://github.com/JuliaLang/julia/issues/6975) > >> >>> > >> >>> - b) A lack of documentation for informal interfaces, such as the > >> >>> methods that AbstractArray objects must implement. > >> >>> > >> >>> (2) A lack of delegation when you make wrapper types: > >> >>> https://github.com/JuliaLang/julia/pull/3292 > >> >>> > >> >>> The first has moved forward a bunch thanks to Mauro's work. The > second > >> >>> has not gotten much further, although Kevin Squire wrote a different > >> >>> delegate macro that's noticeably better than the draft I wrote. > >> >>> > >> >>> -- John > >> >>> > >> >>> On Nov 21, 2014, at 2:31 PM, Sebastian Good < > >> >>> sebast...@palladiumconsulting.com> wrote: > >> >>> > >> >>> In implementing new kinds of numbers, I've found it difficult to > know > >> >>> just how many functions I need to implement for the general library > to > >> >>> "just work" on them. Take as an example a byte-swapped, e.g. > >> big-endian, > >> >>> integer. This is handy when doing memory-mapped I/O on a file with > data > >> >>> written in network order. It would be nice to just implement, say, > >> >>> Int32BigEndian and have it act like a real number. (Then I could > just > >> >>> reinterpret a mmaped array and work directly off it) In general, > we'd > >> >>> convert to Int32 at the earliest opportunity we had. For instance > the > >> >>> following macro introduces a new type which claims to be derived > from > >> >>> $base_type, and implements conversions and promotion rules to get it > >> into a > >> >>> native form ($n_type) whenever it's used. > >> >>> > >> >>> macro encoded_bitstype(name, base_type, bits_type, n_type, to_n, > >> from_n) > >> >>> quote > >> >>> immutable $name <: $base_type > >> >>> bits::$bits_type > >> >>> end > >> >>> > >> >>> Base.bits(x::$name) = bits(x.bits) > >> >>> Base.bswap(x::$name) = $name(bswap(x.bits)) > >> >>> > >> >>> Base.convert(::Type{$n_type}, x::$name) = $to_n(x.bits) > >> >>> Base.convert(::Type{$name}, x::$n_type) = $name($from_n(x)) > >> >>> Base.promote_rule(::Type{$name}, ::Type{$n_type}) = $n_type > >> >>> Base.promote_rule(::Type{$name}, ::Type{$base_type}) = > $n_type > >> >>> end > >> >>> end > >> >>> > >> >>> I can use it like this > >> >>> > >> >>> @encoded_bitstype(Int32BigEndian, Signed, Int32, Int32, bswap, > bswap) > >> >>> > >> >>> But unfortunately, it doesn't work out of the box because the > >> conversions > >> >>> need to be explicit. I noticed that many of the math functions > promote > >> >>> their arguments to a common type, but the following trick doesn't > work, > >> >>> presumably because the promotion algorithm doesn't ask to promote > types > >> >>> that are already identical. > >> >>> > >> >>> Base.promote_rule(::Type{$name}, ::Type{$name}) = $n_type > >> >>> > >> >>> It seems like there are a couple of issues this raises, and I know > I've > >> >>> seen similar questions on this list as people implement new kinds of > >> >>> things, e.g. exotic matrices. > >> >>> > >> >>> 1. One possibility would be to allow an implicit promotion, perhaps > >> >>> expressed as the self-promotion above. I say I'm a Int32BigEndian, > or > >> >>> CompressedVector, or what have you, and provide a way to turn me > into > >> an > >> >>> Int32 or Vector implicitly to take advantage of all the functions > >> already > >> >>> written on those types. I'm not sure this is a great option for the > >> >>> language since it's been explicitly avoided elsewhere. but I'm > curious > >> if > >> >>> there have been any discussions in this direction > >> >>> > >> >>> 2. If instead I want to say "this new type acts like an Integer", > >> there's > >> >>> no canonical place for me to find out what all the functions are I > >> need to > >> >>> implement. Ultimately, these are like Haskell's typeclasses, Ord, > Eq, > >> etc. > >> >>> By trial and error, we can determine many of them and implement them > >> this > >> >>> way > >> >>> > >> >>> macro as_number(name, n_type) > >> >>> quote > >> >>> global +(x::$name, y::$name) = +(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> global *(x::$name, y::$name) = *(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> global -(x::$name, y::$name) = -(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> global -(x::$name) = -convert($n_type, x) > >> >>> global /(x::$name, y::$name) = /(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> global ^(x::$name, y::$name) = ^(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> global ==(x::$name, y::$name) = (==)(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> global < (x::$name, y::$name) = (< )(convert($n_type, x), > >> >>> convert($n_type, y)) > >> >>> Base.flipsign(x::$name, y::$name) = > >> >>> Base.flipsign(convert($n_type, x), convert($n_type, y)) > >> >>> end > >> >>> end > >> >>> > >> >>> But I don't know if I've found them all, and my guesses may well > change > >> >>> as implementation details inside the base library change. Gradual > >> typing is > >> >>> great, but with such a powerful base library already in place, it > >> would be > >> >>> good to have a facility to know which functions are associated with > >> which > >> >>> named behaviors. > >> >>> > >> >>> Since we already have abstract classes in place, e.g. Signed, > Number, > >> >>> etc., it would be natural to extract a list of functions which > operate > >> on > >> >>> them, or, even better, allow the type declarer to specify which > >> functions > >> >>> *should* operate on that abstract class, typeclass or interface > style? > >> >>> > >> >>> Are there any recommendations in place, or updates to the language > >> >>> planned, to address these sorts of topics? > >> >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> >> > >> > >> > >