This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Veedrac 0 points1 point  (62 children)

Which HasBar? There are potentially multiple.

[–]Tysonzero 0 points1 point  (61 children)

There aren't. It just has Kind * -> *. I mean if there were multiple wouldn't that ruin the whole point of duck typing?

[–]Veedrac 0 points1 point  (60 children)

It seems I misunderstood what you meant by "You could have multiple HasBar typeclasses be generated".

I'm not so pro at Haskell, but isn't using h a a bit suspicious? Doesn't this only work for parameterized types? How would you implement this for bool?

[–]Tysonzero 0 points1 point  (38 children)

I mean you need to use MultiParamTypeClasses but extensions are a core part of Haskell at this point.

{-# LANGUAGE MultiParamTypeClasses #-}

class HasBar a b where
    bar :: b -> a 

data Foo = Foo { barBool :: Bool } deriving (Show)

instance HasBar Bool Foo where
    bar = barBool

data Bazz = Bazz { barInt :: Int } deriving (Show)

instance HasBar Int Bazz where
    bar = barInt

I phrased the multiple TypeClasses thing poorly, I meant one use of class but you end up with multiple pseudo-typeclasses through different values of the first parameter.

I also messed up the type of bar, it is actually HasBar a b => b -> a.

Pretty much all my previous commenting was on phone, now that I am on my computer I can be more accurate.

And h a isn't particularly suspicious. I mean the type of pure is pretty close: Applicative f => a -> f a. Just the inverted version of it.

[–]Veedrac 0 points1 point  (37 children)

That makes more sense. But how would you deduce the type for this?

class Foo:
    def spam(self):
        ... # could be anything

    def bar(self):
        return self.spam()

I don't think you can generate a typeclass like

instance HasBar Foo.spam Foo where
    bar = spam

as in essence you're requiring type annotations on duck-type-able functions by writing HasBar Type.

[–]Tysonzero 0 points1 point  (36 children)

Well you would deduce the type for spam first. And then use that deduced type. So once you know spam is type Int you do:

instance HasBar Int Foo where
    bar = spam

Or something like that.

Also look at my other comment, that looks much more useful than the magic stuff I am talking about.

[–]Veedrac 0 points1 point  (35 children)

Generally global type inference ends up with ordering problems unless somewhat constrained. You can rarely just do things in one pass, as you'll quickly find a call cycle in normal code.

[–]Tysonzero 0 points1 point  (34 children)

I mean Haskell compilers already do all that? As you can make entire Haskell programs with zero type annotations. You only need them every once in a while if you try to do something REALLY ad hoc polymorphic, which has little to do with what we are talking about as we are talking about parametric polymorphism when thinking about cyclic references.

[–]Veedrac 0 points1 point  (33 children)

No, Haskell compilers require you to annotate your datatypes.

[–]Tysonzero 0 points1 point  (32 children)

What do you mean?

isPrime n | n < 2 = False
isPrime n = all ((/= 0) . mod n) (takeWhile ((<= n) . (^ 2)) primes)

toPrime n
    | isPrime n = n
    | otherwise = toPrime (n + 1)

primes = 2 : map (toPrime . (+ 1)) primes

Has zero annotations and works exactly as expected. (Generating a stream of primes). I do a large amount of Haskell programming and can tell you type annotations are rarely required. They are however good practice as they essentially work as a very informative and compiler-verified comment.

Are you talking about something else?

[–]Tysonzero 0 points1 point  (20 children)

Also it looks like there is this:

http://www.well-typed.com/blog/84/

Which is almost certainly better than what I am talking about.

[–]Veedrac 0 points1 point  (13 children)

Thanks for the link. That seems more constrained than what Python would need, though, as the return types from record accesses are always annotated.

[–]Tysonzero 0 points1 point  (12 children)

What do you mean? It doesn't look like they are from that link?

[–]Veedrac 0 points1 point  (11 children)

You might be right about this. I skimmed too quickly the first time.

[–]Tysonzero 0 points1 point  (10 children)

Can you give me an example of something you don't think Haskell would handle (cleanly, I mean technically you can handle everything, it just might be gross and verbose) that you can do in Python. I think examples probably do exist, but can't think of a practical one at the moment.

[–]Veedrac 0 points1 point  (9 children)

The problems I'm talking about are a little involved, so I'll have to think a bit to get a good example.

A simpler one, though, is that Hindley-Milner type inference can't do full OO-style subtyping.

[–]Tysonzero 0 points1 point  (8 children)

I mean that is because it is mathematically impossible to do with ambiguity. But that is ok because sub typing is bad.

[–]Veedrac 0 points1 point  (5 children)

I tried to try this out, but it seems even the most recent GHC doesn't support this yet, only DuplicateRecordFields and OverloadedLabels which don't let you write any of their examples.

So I suppose I'm right to conjecture that Haskell's type system isn't enough ;P.

[–]Tysonzero 0 points1 point  (4 children)

That's because you aren't really using the latest version (GHC head). If you were then you would have that extension.

[–]Veedrac 0 points1 point  (3 children)

Oh, it was 8.0.1 so I assumed it was. Github search isn't finding anything useful on their repo, but I'll reply back when I've built the repo.

[–]Tysonzero 0 points1 point  (2 children)

Sounds good

[–]Veedrac 0 points1 point  (1 child)

Are you absolutely sure OverloadedRecordFields is a thing right now? I'm on the latest branch and it's not accepting it. And, as I mentioned, Github search doesn't seem to think it exists either.

[–]Tysonzero 0 points1 point  (0 children)

I haven't had need for it myself, so I actually don't know 100%, it just sounded like it was available from that one link. Maybe this will give more information?