Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-14 Thread Simon Peyton-Jones
|   {-# LANGUAGE TypeFamilies #-}
|  
|   type family F a
|  
|   foo :: F a
|   foo = undefined
|  
|   bar :: F a
|   bar = foo

There is a real difficulty here with type-checking 'bar'.  (And that difficulty 
is why 'foo' is also rejected.)

Namely, when typechecking 'bar', we must instantiate foo with an unknown type, 
say alpha.  So now we must find a type 'alpha' such that
F a ~ F alpha
Certainly alpha=1 is one solution, but there might be others.  For example, 
suppose
type instance F [b] = F b
Then alpha=[a] would also be a solution.

In this particular case any solution will do, but suppose there was an addition 
constraint (C alpha) arising from the right hand side, where C is a class.  
Then if we had
instance C [b] where ...
then the second solution (alpha=[a]) would work, but not the first.  This can 
get arbitrarily complicated, and GHC's type inference does not search various 
solutions; it follows one path.

The solution is to provide a way to fix alpha. For example,
foo :: a - F a
is fine.

Simon


| -Original Message-
| From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-
| users-boun...@haskell.org] On Behalf Of Richard Eisenberg
| Sent: 14 January 2013 03:47
| To: Conal Elliott
| Cc: glasgow-haskell-us...@haskell.org; Haskell Cafe
| Subject: Re: Advice on type families and non-injectivity?
| 
| Hi Conal,
| 
| I agree that your initial example is a little puzzling, and I'm glad
| that the new ambiguity checker prevents both definitions, not just one.
| 
| However, your initial question seems broader than just this example. I
| have run into this problem (wanting injective type functions) several
| times myself, and have been successful at finding workarounds. But, I
| can't think of any unifying principle or solid advice. If you can post
| more information about your problem, perhaps I or others can contribute.
| 
| For what it's worth, the desire for injective type functions has been
| entered as ticket #6018 in the GHC Trac, but I see you're already on the
| cc: list. I believe Simon PJ has given serious thought to implementing
| this feature and may have even put in some very basic code toward this
| end.
| 
| Richard
| 
| On Jan 13, 2013, at 2:10 PM, Conal Elliott co...@conal.net wrote:
| 
|  I sometimes run into trouble with lack of injectivity for type
| families. I'm trying to understand what's at the heart of these
| difficulties and whether I can avoid them. Also, whether some of the
| obstacles could be overcome with simple improvements to GHC.
| 
|  Here's a simple example:
| 
|   {-# LANGUAGE TypeFamilies #-}
|  
|   type family F a
|  
|   foo :: F a
|   foo = undefined
|  
|   bar :: F a
|   bar = foo
| 
|  The error message:
| 
|  Couldn't match type `F a' with `F a1'
|  NB: `F' is a type function, and may not be injective
|  In the expression: foo
|  In an equation for `bar': bar = foo
| 
|  A terser (but perhaps subtler) example producing the same error:
| 
|   baz :: F a
|   baz = baz
| 
|  Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.
| 
|  Does the difficulty here have to do with trying to *infer* the type
| and then compare with the given one? Or is there an issue even with type
| *checking* in such cases?
| 
|  Other insights welcome, as well as suggested work-arounds.
| 
|  I know about (injective) data families but don't want to lose the
| convenience of type synonym families.
| 
|  Thanks,  -- Conal
| 
|  ___
|  Glasgow-haskell-users mailing list
|  glasgow-haskell-us...@haskell.org
|  http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
| 
| 
| ___
| Glasgow-haskell-users mailing list
| glasgow-haskell-us...@haskell.org
| http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-14 Thread Conal Elliott

 There is a real difficulty here with type-checking 'bar'.  (And that
 difficulty is why 'foo' is also rejected.)


Oh! Is the definition of 'foo' rejected in recent versions of GHC? My 7.4.1
installation doesn't complain.   -- Conal


On Mon, Jan 14, 2013 at 3:39 AM, Simon Peyton-Jones
simo...@microsoft.comwrote:

 |   {-# LANGUAGE TypeFamilies #-}
 |  
 |   type family F a
 |  
 |   foo :: F a
 |   foo = undefined
 |  
 |   bar :: F a
 |   bar = foo

 There is a real difficulty here with type-checking 'bar'.  (And that
 difficulty is why 'foo' is also rejected.)

 Namely, when typechecking 'bar', we must instantiate foo with an unknown
 type, say alpha.  So now we must find a type 'alpha' such that
 F a ~ F alpha
 Certainly alpha=1 is one solution, but there might be others.  For
 example, suppose
 type instance F [b] = F b
 Then alpha=[a] would also be a solution.

 In this particular case any solution will do, but suppose there was an
 addition constraint (C alpha) arising from the right hand side, where C is
 a class.  Then if we had
 instance C [b] where ...
 then the second solution (alpha=[a]) would work, but not the first.  This
 can get arbitrarily complicated, and GHC's type inference does not search
 various solutions; it follows one path.

 The solution is to provide a way to fix alpha. For example,
 foo :: a - F a
 is fine.

 Simon


 | -Original Message-
 | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-
 | users-boun...@haskell.org] On Behalf Of Richard Eisenberg
 | Sent: 14 January 2013 03:47
 | To: Conal Elliott
 | Cc: glasgow-haskell-us...@haskell.org; Haskell Cafe
 | Subject: Re: Advice on type families and non-injectivity?
 |
 | Hi Conal,
 |
 | I agree that your initial example is a little puzzling, and I'm glad
 | that the new ambiguity checker prevents both definitions, not just one.
 |
 | However, your initial question seems broader than just this example. I
 | have run into this problem (wanting injective type functions) several
 | times myself, and have been successful at finding workarounds. But, I
 | can't think of any unifying principle or solid advice. If you can post
 | more information about your problem, perhaps I or others can contribute.
 |
 | For what it's worth, the desire for injective type functions has been
 | entered as ticket #6018 in the GHC Trac, but I see you're already on the
 | cc: list. I believe Simon PJ has given serious thought to implementing
 | this feature and may have even put in some very basic code toward this
 | end.
 |
 | Richard
 |
 | On Jan 13, 2013, at 2:10 PM, Conal Elliott co...@conal.net wrote:
 |
 |  I sometimes run into trouble with lack of injectivity for type
 | families. I'm trying to understand what's at the heart of these
 | difficulties and whether I can avoid them. Also, whether some of the
 | obstacles could be overcome with simple improvements to GHC.
 | 
 |  Here's a simple example:
 | 
 |   {-# LANGUAGE TypeFamilies #-}
 |  
 |   type family F a
 |  
 |   foo :: F a
 |   foo = undefined
 |  
 |   bar :: F a
 |   bar = foo
 | 
 |  The error message:
 | 
 |  Couldn't match type `F a' with `F a1'
 |  NB: `F' is a type function, and may not be injective
 |  In the expression: foo
 |  In an equation for `bar': bar = foo
 | 
 |  A terser (but perhaps subtler) example producing the same error:
 | 
 |   baz :: F a
 |   baz = baz
 | 
 |  Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.
 | 
 |  Does the difficulty here have to do with trying to *infer* the type
 | and then compare with the given one? Or is there an issue even with type
 | *checking* in such cases?
 | 
 |  Other insights welcome, as well as suggested work-arounds.
 | 
 |  I know about (injective) data families but don't want to lose the
 | convenience of type synonym families.
 | 
 |  Thanks,  -- Conal
 | 
 |  ___
 |  Glasgow-haskell-users mailing list
 |  glasgow-haskell-us...@haskell.org
 |  http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
 |
 |
 | ___
 | Glasgow-haskell-users mailing list
 | glasgow-haskell-us...@haskell.org
 | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-14 Thread Conal Elliott
Thanks, Jake! This suggestion helped a lot.  -- Conal


On Sun, Jan 13, 2013 at 1:59 PM, Jake McArthur jake.mcart...@gmail.comwrote:

 I have a trick that loses a little convenience, but may still be more
 convenient than data families.

 {-# LANGUAGE TypeFamilies #-}

 import Data.Tagged

 type family F a

 foo :: Tagged a (F a)
 foo = Tagged undefined

 bar :: Tagged a (F a)
 bar = foo


 This allows you to use the same newtype wrapper consistently, regardless
 of what the type instance actually is; one of the inconveniences of data
 families is the need to use different constructors for different types.


 On Sun, Jan 13, 2013 at 2:10 PM, Conal Elliott co...@conal.net wrote:

 I sometimes run into trouble with lack of injectivity for type families.
 I'm trying to understand what's at the heart of these difficulties and
 whether I can avoid them. Also, whether some of the obstacles could be
 overcome with simple improvements to GHC.

 Here's a simple example:

  {-# LANGUAGE TypeFamilies #-}
 
  type family F a
 
  foo :: F a
  foo = undefined
 
  bar :: F a
  bar = foo

 The error message:

 Couldn't match type `F a' with `F a1'
 NB: `F' is a type function, and may not be injective
 In the expression: foo
 In an equation for `bar': bar = foo

 A terser (but perhaps subtler) example producing the same error:

  baz :: F a
  baz = baz

 Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.

 Does the difficulty here have to do with trying to *infer* the type and
 then compare with the given one? Or is there an issue even with type
 *checking* in such cases?

 Other insights welcome, as well as suggested work-arounds.

 I know about (injective) data families but don't want to lose the
 convenience of type synonym families.

 Thanks,  -- Conal


 ___
 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] Advice on type families and non-injectivity?

2013-01-14 Thread Simon Peyton-Jones
Oh! Is the definition of 'foo' rejected in recent versions of GHC? My 7.4.1 
installation doesn't complain.   -- Conal

Yes, it is rejected.

Simon

From: conal.elli...@gmail.com [mailto:conal.elli...@gmail.com] On Behalf Of 
Conal Elliott
Sent: 14 January 2013 20:52
To: Simon Peyton-Jones
Cc: Richard Eisenberg; glasgow-haskell-us...@haskell.org; Haskell Cafe
Subject: Re: Advice on type families and non-injectivity?

There is a real difficulty here with type-checking 'bar'.  (And that difficulty 
is why 'foo' is also rejected.)

Oh! Is the definition of 'foo' rejected in recent versions of GHC? My 7.4.1 
installation doesn't complain.   -- Conal

On Mon, Jan 14, 2013 at 3:39 AM, Simon Peyton-Jones 
simo...@microsoft.commailto:simo...@microsoft.com wrote:
|   {-# LANGUAGE TypeFamilies #-}
|  
|   type family F a
|  
|   foo :: F a
|   foo = undefined
|  
|   bar :: F a
|   bar = foo
There is a real difficulty here with type-checking 'bar'.  (And that difficulty 
is why 'foo' is also rejected.)

Namely, when typechecking 'bar', we must instantiate foo with an unknown type, 
say alpha.  So now we must find a type 'alpha' such that
F a ~ F alpha
Certainly alpha=1 is one solution, but there might be others.  For example, 
suppose
type instance F [b] = F b
Then alpha=[a] would also be a solution.

In this particular case any solution will do, but suppose there was an addition 
constraint (C alpha) arising from the right hand side, where C is a class.  
Then if we had
instance C [b] where ...
then the second solution (alpha=[a]) would work, but not the first.  This can 
get arbitrarily complicated, and GHC's type inference does not search various 
solutions; it follows one path.

The solution is to provide a way to fix alpha. For example,
foo :: a - F a
is fine.

Simon


| -Original Message-
| From: 
glasgow-haskell-users-boun...@haskell.orgmailto:glasgow-haskell-users-boun...@haskell.org
 [mailto:glasgow-haskell-mailto:glasgow-haskell-
| users-boun...@haskell.orgmailto:users-boun...@haskell.org] On Behalf Of 
Richard Eisenberg
| Sent: 14 January 2013 03:47
| To: Conal Elliott
| Cc: 
glasgow-haskell-us...@haskell.orgmailto:glasgow-haskell-us...@haskell.org; 
Haskell Cafe
| Subject: Re: Advice on type families and non-injectivity?
|
| Hi Conal,
|
| I agree that your initial example is a little puzzling, and I'm glad
| that the new ambiguity checker prevents both definitions, not just one.
|
| However, your initial question seems broader than just this example. I
| have run into this problem (wanting injective type functions) several
| times myself, and have been successful at finding workarounds. But, I
| can't think of any unifying principle or solid advice. If you can post
| more information about your problem, perhaps I or others can contribute.
|
| For what it's worth, the desire for injective type functions has been
| entered as ticket #6018 in the GHC Trac, but I see you're already on the
| cc: list. I believe Simon PJ has given serious thought to implementing
| this feature and may have even put in some very basic code toward this
| end.
|
| Richard
|
| On Jan 13, 2013, at 2:10 PM, Conal Elliott 
co...@conal.netmailto:co...@conal.net wrote:
|
|  I sometimes run into trouble with lack of injectivity for type
| families. I'm trying to understand what's at the heart of these
| difficulties and whether I can avoid them. Also, whether some of the
| obstacles could be overcome with simple improvements to GHC.
| 
|  Here's a simple example:
| 
|   {-# LANGUAGE TypeFamilies #-}
|  
|   type family F a
|  
|   foo :: F a
|   foo = undefined
|  
|   bar :: F a
|   bar = foo
| 
|  The error message:
| 
|  Couldn't match type `F a' with `F a1'
|  NB: `F' is a type function, and may not be injective
|  In the expression: foo
|  In an equation for `bar': bar = foo
| 
|  A terser (but perhaps subtler) example producing the same error:
| 
|   baz :: F a
|   baz = baz
| 
|  Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.
| 
|  Does the difficulty here have to do with trying to *infer* the type
| and then compare with the given one? Or is there an issue even with type
| *checking* in such cases?
| 
|  Other insights welcome, as well as suggested work-arounds.
| 
|  I know about (injective) data families but don't want to lose the
| convenience of type synonym families.
| 
|  Thanks,  -- Conal
| 
|  ___
|  Glasgow-haskell-users mailing list
|  glasgow-haskell-us...@haskell.orgmailto:glasgow-haskell-us...@haskell.org
|  http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
|
|
| ___
| Glasgow-haskell-users mailing list
| glasgow-haskell-us...@haskell.orgmailto:glasgow-haskell-us...@haskell.org
| http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org

Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-13 Thread Iavor Diatchki
Hello Conal,

The issue with your example is that it is ambiguous, so GHC can't figure
out how to instantiate the use of `foo`.   It might be easier to see why
this is if you write it in this form:

 foo :: (F a ~ b) = b
 foo = ...

Now, we can see that only `b` appears on the RHS of the `=`, so there is
really no way for GHC to figure out what is the intended value for `a`.
 Replacing `a` with a concrete type (such as `Bool`) eliminates the
problem, because now GHC does not need to come up with a value for `a`.
Another way to eliminate the ambiguity would be if `F` was injective---then
we'd know that `b` uniquely determines `a` so again there would be no
ambiguity.

If `F` is not injective, however, the only workaround would be to write the
type in such a way that the function arguments appear in the signature
directly (e.g., something like 'a - F a' would be ok).

-Iavor








On Sun, Jan 13, 2013 at 11:10 AM, Conal Elliott co...@conal.net wrote:

 I sometimes run into trouble with lack of injectivity for type families.
 I'm trying to understand what's at the heart of these difficulties and
 whether I can avoid them. Also, whether some of the obstacles could be
 overcome with simple improvements to GHC.

 Here's a simple example:

  {-# LANGUAGE TypeFamilies #-}
 
  type family F a
 
  foo :: F a
  foo = undefined
 
  bar :: F a
  bar = foo

 The error message:

 Couldn't match type `F a' with `F a1'
 NB: `F' is a type function, and may not be injective
 In the expression: foo
 In an equation for `bar': bar = foo

 A terser (but perhaps subtler) example producing the same error:

  baz :: F a
  baz = baz

 Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.

 Does the difficulty here have to do with trying to *infer* the type and
 then compare with the given one? Or is there an issue even with type
 *checking* in such cases?

 Other insights welcome, as well as suggested work-arounds.

 I know about (injective) data families but don't want to lose the
 convenience of type synonym families.

 Thanks,  -- Conal


 ___
 Glasgow-haskell-users mailing list
 glasgow-haskell-us...@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-13 Thread Conal Elliott
Hi Iavor,

Thanks for the remarks.

so there is really no way for GHC to figure out what is the intended value
 for `a`.


Indeed. Though I wonder: does the type-checker really need to find a
binding for `a` in this case, i.e., given the equation `(forall a. F a) ==
(forall a'. F a')`?

-- Conal


On Sun, Jan 13, 2013 at 11:39 AM, Iavor Diatchki
iavor.diatc...@gmail.comwrote:

 Hello Conal,

 The issue with your example is that it is ambiguous, so GHC can't figure
 out how to instantiate the use of `foo`.   It might be easier to see why
 this is if you write it in this form:

  foo :: (F a ~ b) = b
  foo = ...

 Now, we can see that only `b` appears on the RHS of the `=`, so there is
 really no way for GHC to figure out what is the intended value for `a`.
  Replacing `a` with a concrete type (such as `Bool`) eliminates the
 problem, because now GHC does not need to come up with a value for `a`.
 Another way to eliminate the ambiguity would be if `F` was injective---then
 we'd know that `b` uniquely determines `a` so again there would be no
 ambiguity.

 If `F` is not injective, however, the only workaround would be to write
 the type in such a way that the function arguments appear in the signature
 directly (e.g., something like 'a - F a' would be ok).

 -Iavor








 On Sun, Jan 13, 2013 at 11:10 AM, Conal Elliott co...@conal.net wrote:

  I sometimes run into trouble with lack of injectivity for type
 families. I'm trying to understand what's at the heart of these
 difficulties and whether I can avoid them. Also, whether some of the
 obstacles could be overcome with simple improvements to GHC.

 Here's a simple example:

  {-# LANGUAGE TypeFamilies #-}
 
  type family F a
 
  foo :: F a
  foo = undefined
 
  bar :: F a
  bar = foo

 The error message:

 Couldn't match type `F a' with `F a1'
 NB: `F' is a type function, and may not be injective
 In the expression: foo
 In an equation for `bar': bar = foo

 A terser (but perhaps subtler) example producing the same error:

  baz :: F a
  baz = baz

 Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.

 Does the difficulty here have to do with trying to *infer* the type and
 then compare with the given one? Or is there an issue even with type
 *checking* in such cases?

 Other insights welcome, as well as suggested work-arounds.

 I know about (injective) data families but don't want to lose the
 convenience of type synonym families.

 Thanks,  -- Conal


 ___
 Glasgow-haskell-users mailing list
 glasgow-haskell-us...@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-13 Thread Conal Elliott
Hi Christian,

Given bar :: Bool, I can't see how one could go from Bool to F a =
 Bool and determine a uniquely.


The same question applies to foo :: Bool, right? Yet no error message
there.

Regards, - Conal

On Sun, Jan 13, 2013 at 11:36 AM, Christian Höner zu Siederdissen 
choe...@tbi.univie.ac.at wrote:

 Hi,

 How would you infer a from F a? Given bar :: Bool, I can't see how
 one could go from Bool to F a = Bool and determine a uniquely.

 My question is not completely retorical, if there is an answer I would
 like to know it :-)

 Gruss,
 Christian


 * Conal Elliott co...@conal.net [13.01.2013 20:13]:
 I sometimes run into trouble with lack of injectivity for type
 families.
 I'm trying to understand what's at the heart of these difficulties and
 whether I can avoid them. Also, whether some of the obstacles could be
 overcome with simple improvements to GHC.
 
 Here's a simple example:
 
  {-# LANGUAGE TypeFamilies #-}
 
  type family F a
 
  foo :: F a
  foo = undefined
 
  bar :: F a
  bar = foo
 
 The error message:
 
 Couldn't match type `F a' with `F a1'
 NB: `F' is a type function, and may not be injective
 In the expression: foo
 In an equation for `bar': bar = foo
 
 A terser (but perhaps subtler) example producing the same error:
 
  baz :: F a
  baz = baz
 
 Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.
 
 Does the difficulty here have to do with trying to *infer* the type
 and
 then compare with the given one? Or is there an issue even with type
 *checking* in such cases?
 
 Other insights welcome, as well as suggested work-arounds.
 
 I know about (injective) data families but don't want to lose the
 convenience of type synonym families.
 
 Thanks,  -- Conal

  ___
  Glasgow-haskell-users mailing list
  glasgow-haskell-us...@haskell.org
  http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-13 Thread Iavor Diatchki
Hello,


On Sun, Jan 13, 2013 at 12:05 PM, Conal Elliott co...@conal.net wrote:


 so there is really no way for GHC to figure out what is the intended value
 for `a`.


 Indeed. Though I wonder: does the type-checker really need to find a
 binding for `a` in this case, i.e., given the equation `(forall a. F a) ==
 (forall a'. F a')`?


Wouldn't that make `F` a constant type family, and so one could just skip
the `a` parameter?   Anyway, if there was a way to assert something like
that about a type-function, than there would be no problem.   When
something like that happens (i.e., GHC figures out that it does not know
how to instantiate a type variable, but it is sure that the actual
instantiation does not matter), GHC instantiates the variable a special
type called `Any`, which has a very polymorphic kind.

By the way, Simon recently reworked the ambiguity checker in GHC, and now
HEAD correctly rejects `foo` as being ambiguous (the new ambiguity check
uses exactly what's in your example: a value `f :: S` is ambiguous, if `g
:: S; g = f` results in an error).

-Iavor
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Advice on type families and non-injectivity?

2013-01-13 Thread Jake McArthur
I have a trick that loses a little convenience, but may still be more
convenient than data families.

{-# LANGUAGE TypeFamilies #-}

import Data.Tagged

type family F a

foo :: Tagged a (F a)
foo = Tagged undefined

bar :: Tagged a (F a)
bar = foo


This allows you to use the same newtype wrapper consistently, regardless of
what the type instance actually is; one of the inconveniences of data
families is the need to use different constructors for different types.


On Sun, Jan 13, 2013 at 2:10 PM, Conal Elliott co...@conal.net wrote:

 I sometimes run into trouble with lack of injectivity for type families.
 I'm trying to understand what's at the heart of these difficulties and
 whether I can avoid them. Also, whether some of the obstacles could be
 overcome with simple improvements to GHC.

 Here's a simple example:

  {-# LANGUAGE TypeFamilies #-}
 
  type family F a
 
  foo :: F a
  foo = undefined
 
  bar :: F a
  bar = foo

 The error message:

 Couldn't match type `F a' with `F a1'
 NB: `F' is a type function, and may not be injective
 In the expression: foo
 In an equation for `bar': bar = foo

 A terser (but perhaps subtler) example producing the same error:

  baz :: F a
  baz = baz

 Replacing `a` with a monotype (e.g., `Bool`) eliminates the error.

 Does the difficulty here have to do with trying to *infer* the type and
 then compare with the given one? Or is there an issue even with type
 *checking* in such cases?

 Other insights welcome, as well as suggested work-arounds.

 I know about (injective) data families but don't want to lose the
 convenience of type synonym families.

 Thanks,  -- Conal


 ___
 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] Advice on type families and non-injectivity?

2013-01-13 Thread wren ng thornton

On 1/13/13 3:52 PM, Iavor Diatchki wrote:

On Sun, Jan 13, 2013 at 12:05 PM, Conal Elliott co...@conal.net wrote:

so there is really no way for GHC to figure out what is the intended value
for `a`.


Indeed. Though I wonder: does the type-checker really need to find a
binding for `a` in this case, i.e., given the equation `(forall a. F a) ==
(forall a'. F a')`?


Wouldn't that make `F` a constant type family,


I don't see why. If we translate this to dependent type notation we get:

((a::*) - F a) == ((b::*) - F b)

This equality should hold in virtue of alpha-conversion. What F is, is 
irrelevant; the only thing that matters is that it has kind *-*. In 
particular, it doesn't matter whether F is arbitrary, injective, 
parametric, constant, etc.


The problem is that the above isn't the equation GHC sees. GHC sees:

F a == F b

and it can't infer any correlation between a and b, where one of those 
is universally quantified in the context (the definition of bar) and the 
other is something we need to fabricate to hand off to the polymorphic 
value (the call to foo).


Of course, in this particular case it *ought* to be fine, by 
parametricity in the definition of foo. That is, since we merely need to 
come up with some b, any b, such that F b is the type we need (namely: F 
a), the a we have will suffice for that. So if we're explicit about type 
passing, the following is fine:


foo :: forall b. F b

bar :: forall a. F a
bar = /\a - foo @a

The problem is that while the a is sufficient it's not (in general) 
necessary. And that's the ambiguity GHC is complaining about. GHC can't 
see that foo is parametric in b, and therefore that a is as good as any 
other type.


--
Live well,
~wren

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe