Re: [Haskell-cafe] Class constraints with free type variables and fundeps

2012-09-29 Thread Francesco Mazzoli
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

2012-09-29 Thread Francesco Mazzoli
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

2012-09-29 Thread MigMit
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

2012-09-29 Thread Francesco Mazzoli
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

2012-09-29 Thread Francesco Mazzoli
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

2012-09-29 Thread Gábor Lehel
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

2012-09-29 Thread MigMit

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

2012-09-29 Thread Francesco Mazzoli
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

2012-09-28 Thread Francesco Mazzoli
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

2012-09-28 Thread Francesco Mazzoli
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

2012-09-28 Thread Alexander Solla
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

2012-09-28 Thread Francesco Mazzoli
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

2012-09-28 Thread Alexander Solla
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