Re: [Haskell-cafe] Class constraints with free type variables and fundeps
At Fri, 28 Sep 2012 18:33:23 -0700, Alexander Solla wrote: Only with respect to type inference. I don't understand this comment. I wouldn't have replied with that line of thought if you had just told us what the problem was in the first place. I /was/ saying that you can use explicit type annotations to disambiguate instances. Most of us haven't memorized the Haskell 2010 report. We let the compiler tell us what's wrong and either learn why, or how to fix it. So post your errors. Sorry, I posted in a hurry. Besides, feeding those lines to a compiler before replying takes 10 seconds. By the way, it is rather rude to publicly post a private email... I thought that you had forgot to reply all, as often happens. I also want the discussion to stay on the list, so that people can read in the future. I'm sorry if that email was meant to be private, I saw nothing private about it. Now, on to your real problem. Use TypeFamilies instead: class Foo a where type BarThing a :: * class Foo a = Bar a where foo :: a - BarThing a - b As I mentioned in the original post, `Foo' is outside my control. This is pretty pointless, since you can just refactor into the nearly equivalent: class Foo a class Foo a = Bar a where type BarThing a :: * foo :: a - BarThing a - c It may or may not matter to which family the type synonym belongs. Mine was a contrived example to show the issue. The whole point is to reduce the number of arguments of a class by referring to another class and its fundeps. What is the problem you are actually trying to solve? What I actually (would like to) have is something like this: class (EditDistance algo sym, ListLike full sym) = Search container full algo | container - full, container - algo where methods referencing `sym' This limitation is annoying even without referencing `sym' (which I can avoid to do) since is prevents me from putting constraints that express what the purpose of the class is and will have to be repeated in every instance. Then I'd also like to have newtype TST sym algo = ... instance (Ord sym, ListLike full sym) = Search (TST sym algo) full algo This one is a different problem - it requires UndecidableInstances and I don't understand why. It seems to me that the coverage condition (http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html, point 7.6.3.2) is too strict in these cases. But this is not that important. -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
At Sat, 29 Sep 2012 10:30:07 +0200, Francesco Mazzoli wrote: Then I'd also like to have newtype TST sym algo = ... instance (Ord sym, ListLike full sym) = Search (TST sym algo) full algo This one is a different problem - it requires UndecidableInstances and I don't understand why. It seems to me that the coverage condition (http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html, point 7.6.3.2) is too strict in these cases. But this is not that important. This doesn't make sense with the code posted (which would require sensibly UndecidableInstances), I meant something like this (I don't have actual code to show the problem): data Foo a class Bar a b | a - b class Quux a b | a - b instance Bar a b = Quux (Foo a) b -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
Well, it seems that you can't do exactly what you want. So, the simplest way to do this would be not to make Foo a superclass for Bar: class Bar a where foo :: Foo a b = a - b - c Then you would have to mention Foo everywhere. If you really need, for some reason, to ensure that every Bar instance has a corresponding Foo instance, you can do some oleging this way: data Void b = Void data FooEv a where FooEv :: Foo a b = Void b - FooEv a class Bar a where barFoo :: FooEv a bar :: Foo a b = a - b - c Then, whenever you need Foo methods, you can do pattern-matching: case barFoo :: FooEv a of FooEv (Void :: Void b) - … Now some b is in scope, and there is an instance of Foo a b. On Sep 28, 2012, at 8:36 PM, Francesco Mazzoli f...@mazzo.li wrote: I would expect this to work, maybe with some additional notation (a la ScopedTypeVariables) {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} class Foo a b | a - b class Foo a b = Bar a where foo :: a - b - c The type family equivalent works as expected: {-# LANGUAGE TypeFamilies #-} class Foo a where type T a :: * class Bar a where foo :: a - T a - c I can't use type families because the `Foo' I'm using is in an external library. Is there any way to achieve what I want without adding `b' to `Bar'? -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
At Sat, 29 Sep 2012 13:04:59 +0400, MigMit wrote: Well, it seems that you can't do exactly what you want. So, the simplest way to do this would be not to make Foo a superclass for Bar: class Bar a where foo :: Foo a b = a - b - c Then you would have to mention Foo everywhere. Just to clarify, I already worked my way around that problem. I want to know why I can't do it since it seems a useful feature to have. In fact, I was doing something very similar to what you're proposing before, but I think having the additional argument is better in my code, for various reasons. You can check the actual class here: https://github.com/bitonic/language-spelling/blob/c3b1fa3014983acf41f9248c9507d7404424/Language/Distance/Search/Class.hs, I've left the old version commented. If you really need, for some reason, to ensure that every Bar instance has a corresponding Foo instance, you can do some oleging this way: data Void b = Void data FooEv a where FooEv :: Foo a b = Void b - FooEv a class Bar a where barFoo :: FooEv a bar :: Foo a b = a - b - c Then, whenever you need Foo methods, you can do pattern-matching: case barFoo :: FooEv a of FooEv (Void :: Void b) - … Now some b is in scope, and there is an instance of Foo a b. Well, I'm sure there are endless ways to get around this, but in cases like this the resulting mess far outweighs the advantages :). -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
At Sat, 29 Sep 2012 10:56:29 +0200, Francesco Mazzoli wrote: At Sat, 29 Sep 2012 10:30:07 +0200, Francesco Mazzoli wrote: Then I'd also like to have newtype TST sym algo = ... instance (Ord sym, ListLike full sym) = Search (TST sym algo) full algo This one is a different problem - it requires UndecidableInstances and I don't understand why. It seems to me that the coverage condition (http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html, point 7.6.3.2) is too strict in these cases. But this is not that important. This doesn't make sense with the code posted (which would require sensibly UndecidableInstances), I meant something like this (I don't have actual code to show the problem): data Foo a class Bar a b | a - b class Quux a b | a - b instance Bar a b = Quux (Foo a) b Actually I know why this is the case - instances are picked without looking at the constraints, and there is no backtracking. I guess my brain just can't resist from seeing Prolog in type classes... -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
On Fri, Sep 28, 2012 at 6:36 PM, Francesco Mazzoli f...@mazzo.li wrote: I would expect this to work, maybe with some additional notation (a la ScopedTypeVariables) {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} class Foo a b | a - b class Foo a b = Bar a where foo :: a - b - c The type family equivalent works as expected: {-# LANGUAGE TypeFamilies #-} class Foo a where type T a :: * class Bar a where foo :: a - T a - c I can't use type families because the `Foo' I'm using is in an external library. Is there any way to achieve what I want without adding `b' to `Bar'? I was browsing the GHC bug tracker and accidentally might have found a solution to your problem: http://hackage.haskell.org/trac/ghc/ticket/7100 Basically you have to make a type family to recapitulate the functional dependencies in the instances of Foo: type family FooFD a -- for each instance Foo A B, you have to write: -- type instance FooFD A = B class Foo a (FooFD a) = Bar a where foo :: a - FooFD a - c Anywhere you would use 'b', you use the type family instead. The example in the ticket also had a 'b ~ FooFD a' superclass constraint on Foo itself, which you can't add if you don't control Foo, but I'm not sure what it's necessary for - in my brief tests removing it didn't cause problems. A weakness of this approach is that you have to manually add a type instance for every instance of Foo, which may or may not be a problem in your situation. -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Your ship was destroyed in a monadic eruption. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
On Sep 29, 2012, at 9:49 PM, Gábor Lehel illiss...@gmail.com wrote: On Fri, Sep 28, 2012 at 6:36 PM, Francesco Mazzoli f...@mazzo.li wrote: I would expect this to work, maybe with some additional notation (a la ScopedTypeVariables) {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} class Foo a b | a - b class Foo a b = Bar a where foo :: a - b - c The type family equivalent works as expected: {-# LANGUAGE TypeFamilies #-} class Foo a where type T a :: * class Bar a where foo :: a - T a - c I can't use type families because the `Foo' I'm using is in an external library. Is there any way to achieve what I want without adding `b' to `Bar'? I was browsing the GHC bug tracker and accidentally might have found a solution to your problem: http://hackage.haskell.org/trac/ghc/ticket/7100 Basically you have to make a type family to recapitulate the functional dependencies in the instances of Foo: type family FooFD a Actually, I think it's better to use a class here: class Foo a (FooFD a) = FooProxy a where type FooFD a -- for each instance Foo A B, you have to write: -- type instance FooFD A = B class Foo a (FooFD a) = Bar a where foo :: a - FooFD a - c Anywhere you would use 'b', you use the type family instead. The example in the ticket also had a 'b ~ FooFD a' superclass constraint on Foo itself, which you can't add if you don't control Foo, but I'm not sure what it's necessary for - in my brief tests removing it didn't cause problems. A weakness of this approach is that you have to manually add a type instance for every instance of Foo, which may or may not be a problem in your situation. -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Your ship was destroyed in a monadic eruption. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
At Sat, 29 Sep 2012 19:49:36 +0200, Gábor Lehel wrote: I was browsing the GHC bug tracker and accidentally might have found a solution to your problem: http://hackage.haskell.org/trac/ghc/ticket/7100 Thanks, this makes me feel better. What interested me is not the workarounds, that I had already partly explored, but why the limitation is there in the first place. It turns out that it's because it'd add complexity and type families do it better. Fair enough. Basically you have to make a type family to recapitulate the functional dependencies in the instances of Foo: type family FooFD a -- for each instance Foo A B, you have to write: -- type instance FooFD A = B class Foo a (FooFD a) = Bar a where foo :: a - FooFD a - c Anywhere you would use 'b', you use the type family instead. The example in the ticket also had a 'b ~ FooFD a' superclass constraint on Foo itself, which you can't add if you don't control Foo, but I'm not sure what it's necessary for - in my brief tests removing it didn't cause problems. A weakness of this approach is that you have to manually add a type instance for every instance of Foo, which may or may not be a problem in your situation. I think this method, while useful to show the already shown relation between fundeps and type families, is pointless in reality. The most convenient method in practice, by far, is just to add the dependent part of the fundep explicitly to Bar. Along to the awkwardness you already pointed out of having to declare the family instance for each type, I'm introducing some unfamiliar and unnecessary type family to the user. It adds nothing but confusion. Not to mention that if I stick to fundeps I might hope to use my code with something else apart from GHC. -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Class constraints with free type variables and fundeps
I would expect this to work, maybe with some additional notation (a la ScopedTypeVariables) {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} class Foo a b | a - b class Foo a b = Bar a where foo :: a - b - c The type family equivalent works as expected: {-# LANGUAGE TypeFamilies #-} class Foo a where type T a :: * class Bar a where foo :: a - T a - c I can't use type families because the `Foo' I'm using is in an external library. Is there any way to achieve what I want without adding `b' to `Bar'? -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
CCing the list back. At Fri, 28 Sep 2012 13:30:52 -0700, Alexander Solla wrote: What is the problem, exactly? It looks to me like UndecidableInstances and ScopedTypeVariables (on foo, or its arguments) would be enough. I'm not sure what you mean. I don't see the need for UndecidableInstances, and there is no way I can see to bring the `b' into scope in the type sig for foo, ScopedTypeVariables or not - unless I'm missing something. Also note that as stated, foo's type is a bottom (more specifically, is a function onto bottom, since c is free in the class, and so foo must be parametrically polymorphic in its return type, and so is devoid of real Haskell values). Hopefully that is just an artefact of the translation to Foo's and Bar's. Yeah the type for `foo' is irrelevant, I just needed to put something there. -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
On Fri, Sep 28, 2012 at 5:04 PM, Francesco Mazzoli f...@mazzo.li wrote: CCing the list back. At Fri, 28 Sep 2012 13:30:52 -0700, Alexander Solla wrote: What is the problem, exactly? It looks to me like UndecidableInstances and ScopedTypeVariables (on foo, or its arguments) would be enough. I'm not sure what you mean. I don't see the need for UndecidableInstances, and there is no way I can see to bring the `b' into scope in the type sig for foo, ScopedTypeVariables or not - unless I'm missing something. Well, then what exactly is the problem? Are you getting an error? You don't need to bring 'b' into scope. You will already have real types in scope. instance Foo A B instance Bar A where foo A B = C tryIt = (foo :: A - B - C) A B ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
At Fri, 28 Sep 2012 17:19:36 -0700, Alexander Solla wrote: Well, then what exactly is the problem? Are you getting an error? ...well yes. The error I get with the posted class declarations is Not in scope: type variable `b' at the line with class Foo a b = Bar a where Which I get because all the type vars in the LHS must be referenced on the RHS (or so it seems). Now, in my case the problem does not stop there, because I also want to reference the tyvar on the LHS in a type signature of a method, since in that case there is a fundep on b (`a - b'), which makes `b' decidable if you have `a' and `Foo a b'. You don't need to bring 'b' into scope. You will already have real types in scope. instance Foo A B instance Bar A where foo A B = C Again, I'm not sure what you mean here. -- Francesco * Often in error, never in doubt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class constraints with free type variables and fundeps
On Fri, Sep 28, 2012 at 5:36 PM, Francesco Mazzoli f...@mazzo.li wrote: At Fri, 28 Sep 2012 17:19:36 -0700, Alexander Solla wrote: Well, then what exactly is the problem? Are you getting an error? ...well yes. The error I get with the posted class declarations is Not in scope: type variable `b' at the line with class Foo a b = Bar a where Which I get because all the type vars in the LHS must be referenced on the RHS (or so it seems). Yes, indeed. Now, in my case the problem does not stop there, because I also want to reference the tyvar on the LHS in a type signature of a method, since in that case there is a fundep on b (`a - b'), which makes `b' decidable if you have `a' and `Foo a b'. Only with respect to type inference. You don't need to bring 'b' into scope. You will already have real types in scope. instance Foo A B instance Bar A where foo A B = C Again, I'm not sure what you mean here. I wouldn't have replied with that line of thought if you had just told us what the problem was in the first place. I /was/ saying that you can use explicit type annotations to disambiguate instances. Most of us haven't memorized the Haskell 2010 report. We let the compiler tell us what's wrong and either learn why, or how to fix it. So post your errors. By the way, it is rather rude to publicly post a private email... Now, on to your real problem. Use TypeFamilies instead: class Foo a where type BarThing a :: * class Foo a = Bar a where foo :: a - BarThing a - b This is pretty pointless, since you can just refactor into the nearly equivalent: class Foo a class Foo a = Bar a where type BarThing a :: * foo :: a - BarThing a - c It may or may not matter to which family the type synonym belongs. What is the problem you are actually trying to solve? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe